blob: 41ead59c51df3fa199d0771710b95e56a2e49b9c [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]
Alice Wangfaceff42023-01-19 09:54:38 +0000158fn kernel_footer_with_vbmeta_offset_overwritten_fails_verification() -> Result<()> {
159 // Arrange.
160 let mut kernel = load_latest_signed_kernel()?;
161 let total_len = kernel.len() as u64;
162 let footer = extract_avb_footer(&kernel)?;
163 assert!(footer.vbmeta_offset < total_len);
164 let vbmeta_offset_addr = ptr::addr_of!(footer.vbmeta_offset) as *const u8;
165 // SAFETY: It is safe as both raw pointers `vbmeta_offset_addr` and `footer` are not null.
166 let vbmeta_offset_start =
167 unsafe { vbmeta_offset_addr.offset_from(ptr::addr_of!(footer) as *const u8) };
168 let footer_start = kernel.len() - size_of::<AvbFooter>();
169 let vbmeta_offset_start = footer_start + usize::try_from(vbmeta_offset_start)?;
170
171 let wrong_offsets = [total_len, u64::MAX];
172 for &wrong_offset in wrong_offsets.iter() {
173 // Act.
174 kernel[vbmeta_offset_start..(vbmeta_offset_start + size_of::<u64>())]
175 .copy_from_slice(&wrong_offset.to_be_bytes());
176
177 // Assert.
178 let footer = extract_avb_footer(&kernel)?;
179 assert_eq!(wrong_offset, footer.vbmeta_offset as u64);
180 assert_payload_verification_with_initrd_eq(
181 &kernel,
182 &load_latest_initrd_normal()?,
183 &load_trusted_public_key()?,
184 Err(AvbSlotVerifyError::Io),
185 )?;
186 }
187 Ok(())
188}
189
190#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000191fn tampered_kernel_footer_fails_verification() -> Result<()> {
192 let mut kernel = load_latest_signed_kernel()?;
193 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
194 kernel[avb_footer_index] = !kernel[avb_footer_index];
195
Alice Wang2925b0a2023-01-19 10:44:24 +0000196 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000197 &kernel,
198 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000199 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000200 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000201 )
202}
203
Alice Wang58dac082023-01-13 13:03:59 +0000204#[test]
205fn tampered_vbmeta_fails_verification() -> Result<()> {
206 let mut kernel = load_latest_signed_kernel()?;
207 let footer = extract_avb_footer(&kernel)?;
208 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
209
210 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
211
Alice Wang2925b0a2023-01-19 10:44:24 +0000212 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000213 &kernel,
214 &load_latest_initrd_normal()?,
215 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000216 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wang58dac082023-01-13 13:03:59 +0000217 )
218}
219
220#[test]
221fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
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 let public_key_offset = footer.vbmeta_offset as usize
226 + size_of::<AvbVBMetaImageHeader>()
227 + vbmeta_header.authentication_data_block_size as usize
228 + vbmeta_header.public_key_offset as usize;
229 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
230 let empty_public_key = vec![0u8; public_key_size];
231
232 kernel[public_key_offset..(public_key_offset + public_key_size)]
233 .copy_from_slice(&empty_public_key);
234
Alice Wang2925b0a2023-01-19 10:44:24 +0000235 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000236 &kernel,
237 &load_latest_initrd_normal()?,
238 &empty_public_key,
Alice Wang2925b0a2023-01-19 10:44:24 +0000239 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000240 )?;
Alice Wang2925b0a2023-01-19 10:44:24 +0000241 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000242 &kernel,
243 &load_latest_initrd_normal()?,
244 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000245 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000246 )
247}
248
Alice Wangf06bfd72023-01-19 09:24:21 +0000249#[test]
250fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
251 // From external/avb/libavb/avb_vbmeta_image.h
252 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
253
254 // Arrange.
255 let mut kernel = load_latest_signed_kernel()?;
256 let footer = extract_avb_footer(&kernel)?;
257 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
258 assert_eq!(
259 0, vbmeta_header.flags as u32,
260 "The disable flag should not be set in the latest kernel."
261 );
262 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
263 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
264 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
265 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
266
267 // Act.
268 kernel[flags_offset..(flags_offset + size_of::<u32>())]
269 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
270
271 // Assert.
272 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
273 assert_eq!(
274 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header.flags as u32,
275 "VBMeta verification flag should be disabled now."
276 );
Alice Wang2925b0a2023-01-19 10:44:24 +0000277 assert_payload_verification_with_initrd_eq(
Alice Wangf06bfd72023-01-19 09:24:21 +0000278 &kernel,
279 &load_latest_initrd_normal()?,
280 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000281 Err(AvbSlotVerifyError::Verification),
Alice Wangf06bfd72023-01-19 09:24:21 +0000282 )
283}