blob: 4f00f1e81de97b95710cc5eeb6d73d47c47bf97c [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 Wangf2752862023-01-18 11:51:25 +000028const TEST_IMG_WITH_INITRD_AND_NON_INITRD_DESC_PATH: &str =
29 "test_image_with_initrd_and_non_initrd_desc.img";
Alice Wangbf7fadd2023-01-13 12:18:24 +000030const UNSIGNED_TEST_IMG_PATH: &str = "unsigned_test.img";
31
Alice Wangbf7fadd2023-01-13 12:18:24 +000032const RANDOM_FOOTER_POS: usize = 30;
33
34/// This test uses the Microdroid payload compiled on the fly to check that
35/// the latest payload can be verified successfully.
36#[test]
Alice Wang4e55dd92023-01-11 10:17:01 +000037fn latest_normal_payload_passes_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000038 assert_payload_verification_with_initrd_eq(
Alice Wang4e55dd92023-01-11 10:17:01 +000039 &load_latest_signed_kernel()?,
40 &load_latest_initrd_normal()?,
41 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000042 Ok(DebugLevel::None),
Alice Wang4e55dd92023-01-11 10:17:01 +000043 )
44}
Alice Wangbf7fadd2023-01-13 12:18:24 +000045
Alice Wang4e55dd92023-01-11 10:17:01 +000046#[test]
47fn latest_debug_payload_passes_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000048 assert_payload_verification_with_initrd_eq(
Alice Wang4e55dd92023-01-11 10:17:01 +000049 &load_latest_signed_kernel()?,
50 &load_latest_initrd_debug()?,
51 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000052 Ok(DebugLevel::Full),
Alice Wang4e55dd92023-01-11 10:17:01 +000053 )
Alice Wangbf7fadd2023-01-13 12:18:24 +000054}
55
56#[test]
57fn payload_expecting_no_initrd_passes_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000058 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000059 &fs::read(TEST_IMG_WITH_ONE_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000060 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000061 &load_trusted_public_key()?,
Alice Wang5c1a7562023-01-13 17:19:57 +000062 Ok(DebugLevel::None),
Alice Wang86383df2023-01-11 10:03:56 +000063 )
Alice Wangbf7fadd2023-01-13 12:18:24 +000064}
65
Alice Wang86383df2023-01-11 10:03:56 +000066#[test]
Alice Wangf2752862023-01-18 11:51:25 +000067fn payload_with_non_initrd_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000068 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000069 &fs::read(TEST_IMG_WITH_NON_INITRD_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000070 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000071 &load_trusted_public_key()?,
Alice Wangf2752862023-01-18 11:51:25 +000072 Err(AvbSlotVerifyError::InvalidMetadata),
73 )
74}
75
76#[test]
77fn payload_with_non_initrd_descriptor_fails_verification_with_initrd() -> Result<()> {
78 assert_payload_verification_with_initrd_eq(
79 &fs::read(TEST_IMG_WITH_INITRD_AND_NON_INITRD_DESC_PATH)?,
80 &load_latest_initrd_normal()?,
81 &load_trusted_public_key()?,
82 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wang86383df2023-01-11 10:03:56 +000083 )
84}
85
86#[test]
87fn payload_with_prop_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000088 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000089 &fs::read(TEST_IMG_WITH_PROP_DESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000090 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000091 &load_trusted_public_key()?,
92 Err(AvbSlotVerifyError::InvalidMetadata),
93 )
94}
95
96#[test]
97fn payload_expecting_initrd_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +000098 assert_payload_verification_eq(
Alice Wang86383df2023-01-11 10:03:56 +000099 &load_latest_signed_kernel()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000100 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +0000101 &load_trusted_public_key()?,
102 Err(AvbSlotVerifyError::InvalidMetadata),
103 )
104}
Alice Wangbf7fadd2023-01-13 12:18:24 +0000105
106#[test]
107fn payload_with_empty_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000108 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000109 &load_latest_signed_kernel()?,
110 &load_latest_initrd_normal()?,
111 /*trusted_public_key=*/ &[0u8; 0],
Alice Wang2925b0a2023-01-19 10:44:24 +0000112 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000113 )
114}
115
116#[test]
117fn payload_with_an_invalid_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000118 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000119 &load_latest_signed_kernel()?,
120 &load_latest_initrd_normal()?,
121 /*trusted_public_key=*/ &[0u8; 512],
Alice Wang2925b0a2023-01-19 10:44:24 +0000122 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000123 )
124}
125
126#[test]
127fn payload_with_a_different_valid_public_key_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000128 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000129 &load_latest_signed_kernel()?,
130 &load_latest_initrd_normal()?,
131 &fs::read(PUBLIC_KEY_RSA2048_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000132 Err(AvbSlotVerifyError::PublicKeyRejected),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000133 )
134}
135
136#[test]
Alice Wang5c1a7562023-01-13 17:19:57 +0000137fn payload_with_an_invalid_initrd_fails_verification() -> Result<()> {
138 assert_payload_verification_with_initrd_eq(
139 &load_latest_signed_kernel()?,
140 /*initrd=*/ &fs::read(UNSIGNED_TEST_IMG_PATH)?,
141 &load_trusted_public_key()?,
142 Err(AvbSlotVerifyError::Verification),
143 )
144}
145
146#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000147fn unsigned_kernel_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000148 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000149 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
150 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000151 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000152 Err(AvbSlotVerifyError::Io),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000153 )
154}
155
156#[test]
157fn tampered_kernel_fails_verification() -> Result<()> {
158 let mut kernel = load_latest_signed_kernel()?;
159 kernel[1] = !kernel[1]; // Flip the bits
160
Alice Wang2925b0a2023-01-19 10:44:24 +0000161 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000162 &kernel,
163 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000164 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000165 Err(AvbSlotVerifyError::Verification),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000166 )
167}
168
169#[test]
Alice Wangfaceff42023-01-19 09:54:38 +0000170fn kernel_footer_with_vbmeta_offset_overwritten_fails_verification() -> Result<()> {
171 // Arrange.
172 let mut kernel = load_latest_signed_kernel()?;
173 let total_len = kernel.len() as u64;
174 let footer = extract_avb_footer(&kernel)?;
175 assert!(footer.vbmeta_offset < total_len);
176 let vbmeta_offset_addr = ptr::addr_of!(footer.vbmeta_offset) as *const u8;
177 // SAFETY: It is safe as both raw pointers `vbmeta_offset_addr` and `footer` are not null.
178 let vbmeta_offset_start =
179 unsafe { vbmeta_offset_addr.offset_from(ptr::addr_of!(footer) as *const u8) };
180 let footer_start = kernel.len() - size_of::<AvbFooter>();
181 let vbmeta_offset_start = footer_start + usize::try_from(vbmeta_offset_start)?;
182
183 let wrong_offsets = [total_len, u64::MAX];
184 for &wrong_offset in wrong_offsets.iter() {
185 // Act.
186 kernel[vbmeta_offset_start..(vbmeta_offset_start + size_of::<u64>())]
187 .copy_from_slice(&wrong_offset.to_be_bytes());
188
189 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900190 let footer = extract_avb_footer(&kernel)?;
191 // footer is unaligned; copy vbmeta_offset to local variable
192 let vbmeta_offset = footer.vbmeta_offset;
193 assert_eq!(wrong_offset, vbmeta_offset);
Alice Wangfaceff42023-01-19 09:54:38 +0000194 assert_payload_verification_with_initrd_eq(
195 &kernel,
196 &load_latest_initrd_normal()?,
197 &load_trusted_public_key()?,
198 Err(AvbSlotVerifyError::Io),
199 )?;
200 }
201 Ok(())
202}
203
204#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000205fn tampered_kernel_footer_fails_verification() -> Result<()> {
206 let mut kernel = load_latest_signed_kernel()?;
207 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
208 kernel[avb_footer_index] = !kernel[avb_footer_index];
209
Alice Wang2925b0a2023-01-19 10:44:24 +0000210 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000211 &kernel,
212 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000213 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000214 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000215 )
216}
217
Alice Wang58dac082023-01-13 13:03:59 +0000218#[test]
Alice Wang75d05632023-01-25 13:31:18 +0000219fn extended_initrd_fails_verification() -> Result<()> {
220 let mut initrd = load_latest_initrd_normal()?;
221 initrd.extend(b"androidboot.vbmeta.digest=1111");
222
223 assert_payload_verification_with_initrd_eq(
224 &load_latest_signed_kernel()?,
225 &initrd,
226 &load_trusted_public_key()?,
227 Err(AvbSlotVerifyError::Verification),
228 )
229}
230
231#[test]
Alice Wang58dac082023-01-13 13:03:59 +0000232fn tampered_vbmeta_fails_verification() -> Result<()> {
233 let mut kernel = load_latest_signed_kernel()?;
234 let footer = extract_avb_footer(&kernel)?;
235 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
236
237 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
238
Alice Wang2925b0a2023-01-19 10:44:24 +0000239 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000240 &kernel,
241 &load_latest_initrd_normal()?,
242 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000243 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wang58dac082023-01-13 13:03:59 +0000244 )
245}
246
247#[test]
248fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
249 let mut kernel = load_latest_signed_kernel()?;
250 let footer = extract_avb_footer(&kernel)?;
251 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
252 let public_key_offset = footer.vbmeta_offset as usize
253 + size_of::<AvbVBMetaImageHeader>()
254 + vbmeta_header.authentication_data_block_size as usize
255 + vbmeta_header.public_key_offset as usize;
256 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
257 let empty_public_key = vec![0u8; public_key_size];
258
259 kernel[public_key_offset..(public_key_offset + public_key_size)]
260 .copy_from_slice(&empty_public_key);
261
Alice Wang2925b0a2023-01-19 10:44:24 +0000262 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000263 &kernel,
264 &load_latest_initrd_normal()?,
265 &empty_public_key,
Alice Wang2925b0a2023-01-19 10:44:24 +0000266 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000267 )?;
Alice Wang2925b0a2023-01-19 10:44:24 +0000268 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000269 &kernel,
270 &load_latest_initrd_normal()?,
271 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000272 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000273 )
274}
275
Alice Wangf06bfd72023-01-19 09:24:21 +0000276#[test]
277fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
278 // From external/avb/libavb/avb_vbmeta_image.h
279 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
280
281 // Arrange.
282 let mut kernel = load_latest_signed_kernel()?;
283 let footer = extract_avb_footer(&kernel)?;
284 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900285
286 // vbmeta_header is unaligned; copy flags to local variable
287 let vbmeta_header_flags = vbmeta_header.flags;
288 assert_eq!(0, vbmeta_header_flags, "The disable flag should not be set in the latest kernel.");
Alice Wangf06bfd72023-01-19 09:24:21 +0000289 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
290 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
291 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
292 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
293
294 // Act.
295 kernel[flags_offset..(flags_offset + size_of::<u32>())]
296 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
297
298 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900299 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
300 // vbmeta_header is unaligned; copy flags to local variable
301 let vbmeta_header_flags = vbmeta_header.flags;
302 assert_eq!(
303 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header_flags,
304 "VBMeta verification flag should be disabled now."
305 );
Alice Wang2925b0a2023-01-19 10:44:24 +0000306 assert_payload_verification_with_initrd_eq(
Alice Wangf06bfd72023-01-19 09:24:21 +0000307 &kernel,
308 &load_latest_initrd_normal()?,
309 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000310 Err(AvbSlotVerifyError::Verification),
Alice Wangf06bfd72023-01-19 09:24:21 +0000311 )
312}