blob: f0967eb423e87c97a8387d7da7d39149a3378758 [file] [log] [blame]
Alice Wangbf7fadd2023-01-13 12:18:24 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Alice Wang2925b0a2023-01-19 10:44:24 +000017mod utils;
Alice Wangbf7fadd2023-01-13 12:18:24 +000018
Alice Wang2925b0a2023-01-19 10:44:24 +000019use anyhow::Result;
20use avb_bindgen::{AvbFooter, AvbVBMetaImageHeader};
Alice Wang5c1a7562023-01-13 17:19:57 +000021use pvmfw_avb::{AvbSlotVerifyError, DebugLevel};
Alice Wang2925b0a2023-01-19 10:44:24 +000022use std::{fs, mem::size_of, ptr};
23use utils::*;
24
Alice Wangbf7fadd2023-01-13 12:18:24 +000025const TEST_IMG_WITH_ONE_HASHDESC_PATH: &str = "test_image_with_one_hashdesc.img";
Alice Wang86383df2023-01-11 10:03:56 +000026const TEST_IMG_WITH_PROP_DESC_PATH: &str = "test_image_with_prop_desc.img";
27const TEST_IMG_WITH_NON_INITRD_HASHDESC_PATH: &str = "test_image_with_non_initrd_hashdesc.img";
Alice Wangbf7fadd2023-01-13 12:18:24 +000028const UNSIGNED_TEST_IMG_PATH: &str = "unsigned_test.img";
29
Alice Wangbf7fadd2023-01-13 12:18:24 +000030const RANDOM_FOOTER_POS: usize = 30;
31
32/// This test uses the Microdroid payload compiled on the fly to check that
33/// the latest payload can be verified successfully.
34#[test]
Alice Wang4e55dd92023-01-11 10:17:01 +000035fn latest_normal_payload_passes_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000036 assert_payload_verification_with_initrd_eq(
Alice Wang4e55dd92023-01-11 10:17:01 +000037 &load_latest_signed_kernel()?,
38 &load_latest_initrd_normal()?,
39 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000040 Ok(DebugLevel::None),
Alice Wang4e55dd92023-01-11 10:17:01 +000041 )
42}
Alice Wangbf7fadd2023-01-13 12:18:24 +000043
Alice Wang4e55dd92023-01-11 10:17:01 +000044#[test]
45fn latest_debug_payload_passes_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000046 assert_payload_verification_with_initrd_eq(
Alice Wang4e55dd92023-01-11 10:17:01 +000047 &load_latest_signed_kernel()?,
48 &load_latest_initrd_debug()?,
49 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000050 Ok(DebugLevel::Full),
Alice Wang4e55dd92023-01-11 10:17:01 +000051 )
Alice Wangbf7fadd2023-01-13 12:18:24 +000052}
53
54#[test]
55fn payload_expecting_no_initrd_passes_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000056 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000057 &fs::read(TEST_IMG_WITH_ONE_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000058 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000059 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000060 Ok(DebugLevel::None),
Alice Wang86383df2023-01-11 10:03:56 +000061 )
Alice Wangbf7fadd2023-01-13 12:18:24 +000062}
63
Alice Wang86383df2023-01-11 10:03:56 +000064#[test]
65fn payload_with_non_initrd_descriptor_passes_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000066 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000067 &fs::read(TEST_IMG_WITH_NON_INITRD_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000068 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000069 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000070 Ok(DebugLevel::None),
Alice Wang86383df2023-01-11 10:03:56 +000071 )
72}
73
74#[test]
75fn payload_with_prop_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000076 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000077 &fs::read(TEST_IMG_WITH_PROP_DESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000078 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000079 &load_trusted_public_key()?,
80 Err(AvbSlotVerifyError::InvalidMetadata),
81 )
82}
83
84#[test]
85fn payload_expecting_initrd_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000086 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000087 &load_latest_signed_kernel()?,
Alice Wang2925b0a2023-01-19 10:44:24 +000088 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000089 &load_trusted_public_key()?,
90 Err(AvbSlotVerifyError::InvalidMetadata),
91 )
92}
Alice Wangbf7fadd2023-01-13 12:18:24 +000093
94#[test]
95fn payload_with_empty_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000096 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +000097 &load_latest_signed_kernel()?,
98 &load_latest_initrd_normal()?,
99 /*trusted_public_key=*/ &[0u8; 0],
Alice Wang2925b0a2023-01-19 10:44:24 +0000100 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000101 )
102}
103
104#[test]
105fn payload_with_an_invalid_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000106 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000107 &load_latest_signed_kernel()?,
108 &load_latest_initrd_normal()?,
109 /*trusted_public_key=*/ &[0u8; 512],
Alice Wang2925b0a2023-01-19 10:44:24 +0000110 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000111 )
112}
113
114#[test]
115fn payload_with_a_different_valid_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000116 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000117 &load_latest_signed_kernel()?,
118 &load_latest_initrd_normal()?,
119 &fs::read(PUBLIC_KEY_RSA2048_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000120 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000121 )
122}
123
124#[test]
Alice Wang5c1a7562023-01-13 17:19:57 +0000125fn payload_with_an_invalid_initrd_fails_verification() -> Result<()> {
126 assert_payload_verification_with_initrd_eq(
127 &load_latest_signed_kernel()?,
128 /*initrd=*/ &fs::read(UNSIGNED_TEST_IMG_PATH)?,
129 &load_trusted_public_key()?,
130 Err(AvbSlotVerifyError::Verification),
131 )
132}
133
134#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000135fn unsigned_kernel_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000136 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000137 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
138 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000139 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000140 Err(AvbSlotVerifyError::Io),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000141 )
142}
143
144#[test]
145fn tampered_kernel_fails_verification() -> Result<()> {
146 let mut kernel = load_latest_signed_kernel()?;
147 kernel[1] = !kernel[1]; // Flip the bits
148
Alice Wang2925b0a2023-01-19 10:44:24 +0000149 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000150 &kernel,
151 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000152 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000153 Err(AvbSlotVerifyError::Verification),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000154 )
155}
156
157#[test]
158fn tampered_kernel_footer_fails_verification() -> Result<()> {
159 let mut kernel = load_latest_signed_kernel()?;
160 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
161 kernel[avb_footer_index] = !kernel[avb_footer_index];
162
Alice Wang2925b0a2023-01-19 10:44:24 +0000163 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000164 &kernel,
165 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000166 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000167 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000168 )
169}
170
Alice Wang58dac082023-01-13 13:03:59 +0000171#[test]
172fn tampered_vbmeta_fails_verification() -> Result<()> {
173 let mut kernel = load_latest_signed_kernel()?;
174 let footer = extract_avb_footer(&kernel)?;
175 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
176
177 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
178
Alice Wang2925b0a2023-01-19 10:44:24 +0000179 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000180 &kernel,
181 &load_latest_initrd_normal()?,
182 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000183 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wang58dac082023-01-13 13:03:59 +0000184 )
185}
186
187#[test]
188fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
189 let mut kernel = load_latest_signed_kernel()?;
190 let footer = extract_avb_footer(&kernel)?;
191 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
192 let public_key_offset = footer.vbmeta_offset as usize
193 + size_of::<AvbVBMetaImageHeader>()
194 + vbmeta_header.authentication_data_block_size as usize
195 + vbmeta_header.public_key_offset as usize;
196 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
197 let empty_public_key = vec![0u8; public_key_size];
198
199 kernel[public_key_offset..(public_key_offset + public_key_size)]
200 .copy_from_slice(&empty_public_key);
201
Alice Wang2925b0a2023-01-19 10:44:24 +0000202 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000203 &kernel,
204 &load_latest_initrd_normal()?,
205 &empty_public_key,
Alice Wang2925b0a2023-01-19 10:44:24 +0000206 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000207 )?;
Alice Wang2925b0a2023-01-19 10:44:24 +0000208 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000209 &kernel,
210 &load_latest_initrd_normal()?,
211 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000212 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000213 )
214}
215
Alice Wangf06bfd72023-01-19 09:24:21 +0000216#[test]
217fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
218 // From external/avb/libavb/avb_vbmeta_image.h
219 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
220
221 // Arrange.
222 let mut kernel = load_latest_signed_kernel()?;
223 let footer = extract_avb_footer(&kernel)?;
224 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
225 assert_eq!(
226 0, vbmeta_header.flags as u32,
227 "The disable flag should not be set in the latest kernel."
228 );
229 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
230 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
231 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
232 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
233
234 // Act.
235 kernel[flags_offset..(flags_offset + size_of::<u32>())]
236 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
237
238 // Assert.
239 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
240 assert_eq!(
241 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header.flags as u32,
242 "VBMeta verification flag should be disabled now."
243 );
Alice Wang2925b0a2023-01-19 10:44:24 +0000244 assert_payload_verification_with_initrd_eq(
Alice Wangf06bfd72023-01-19 09:24:21 +0000245 &kernel,
246 &load_latest_initrd_normal()?,
247 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000248 Err(AvbSlotVerifyError::Verification),
Alice Wangf06bfd72023-01-19 09:24:21 +0000249 )
250}