blob: 1d7369d687c31ace6ebff06830c33fc7081ec716 [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 Wang1f0add02023-01-23 16:22:53 +000019use anyhow::{anyhow, Result};
Alice Wang2925b0a2023-01-19 10:44:24 +000020use avb_bindgen::{AvbFooter, AvbVBMetaImageHeader};
Pierre-Clément Tosi81ca0802023-02-14 10:41:38 +000021use pvmfw_avb::{verify_payload, AvbSlotVerifyError, DebugLevel, VerifiedBootData};
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 Wang1f0add02023-01-23 16:22:53 +000038 assert_latest_payload_verification_passes(
Alice Wang4e55dd92023-01-11 10:17:01 +000039 &load_latest_initrd_normal()?,
Alice Wang1f0add02023-01-23 16:22:53 +000040 b"initrd_normal",
41 DebugLevel::None,
Alice Wang4e55dd92023-01-11 10:17:01 +000042 )
43}
Alice Wangbf7fadd2023-01-13 12:18:24 +000044
Alice Wang4e55dd92023-01-11 10:17:01 +000045#[test]
46fn latest_debug_payload_passes_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000047 assert_latest_payload_verification_passes(
Alice Wang4e55dd92023-01-11 10:17:01 +000048 &load_latest_initrd_debug()?,
Alice Wang1f0add02023-01-23 16:22:53 +000049 b"initrd_debug",
50 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 Wang1f0add02023-01-23 16:22:53 +000056 let verified_boot_data = verify_payload(
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 Wang86383df2023-01-11 10:03:56 +000060 )
Alice Wang1f0add02023-01-23 16:22:53 +000061 .map_err(|e| anyhow!("Verification failed. Error: {}", e))?;
62
Pierre-Clément Tosi81ca0802023-02-14 10:41:38 +000063 let kernel_digest = hash(&[&hex::decode("1111")?, &fs::read(UNSIGNED_TEST_IMG_PATH)?]);
64 let expected_boot_data =
65 VerifiedBootData { debug_level: DebugLevel::None, kernel_digest, initrd_digest: None };
66 assert_eq!(expected_boot_data, verified_boot_data);
67
Alice Wang1f0add02023-01-23 16:22:53 +000068 Ok(())
Alice Wangbf7fadd2023-01-13 12:18:24 +000069}
70
Alice Wang86383df2023-01-11 10:03:56 +000071#[test]
Alice Wangf2752862023-01-18 11:51:25 +000072fn payload_with_non_initrd_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000073 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +000074 &fs::read(TEST_IMG_WITH_NON_INITRD_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000075 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000076 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +000077 AvbSlotVerifyError::InvalidMetadata,
Alice Wangf2752862023-01-18 11:51:25 +000078 )
79}
80
81#[test]
82fn payload_with_non_initrd_descriptor_fails_verification_with_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000083 assert_payload_verification_with_initrd_fails(
Alice Wangf2752862023-01-18 11:51:25 +000084 &fs::read(TEST_IMG_WITH_INITRD_AND_NON_INITRD_DESC_PATH)?,
85 &load_latest_initrd_normal()?,
86 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +000087 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +000088 )
89}
90
91#[test]
92fn payload_with_prop_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000093 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +000094 &fs::read(TEST_IMG_WITH_PROP_DESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000095 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000096 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +000097 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +000098 )
99}
100
101#[test]
102fn payload_expecting_initrd_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000103 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +0000104 &load_latest_signed_kernel()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000105 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +0000106 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000107 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +0000108 )
109}
Alice Wangbf7fadd2023-01-13 12:18:24 +0000110
111#[test]
112fn payload_with_empty_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000113 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000114 &load_latest_signed_kernel()?,
115 &load_latest_initrd_normal()?,
116 /*trusted_public_key=*/ &[0u8; 0],
Alice Wang1f0add02023-01-23 16:22:53 +0000117 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000118 )
119}
120
121#[test]
122fn payload_with_an_invalid_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000123 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000124 &load_latest_signed_kernel()?,
125 &load_latest_initrd_normal()?,
126 /*trusted_public_key=*/ &[0u8; 512],
Alice Wang1f0add02023-01-23 16:22:53 +0000127 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000128 )
129}
130
131#[test]
132fn payload_with_a_different_valid_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000133 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000134 &load_latest_signed_kernel()?,
135 &load_latest_initrd_normal()?,
136 &fs::read(PUBLIC_KEY_RSA2048_PATH)?,
Alice Wang1f0add02023-01-23 16:22:53 +0000137 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000138 )
139}
140
141#[test]
Alice Wang5c1a7562023-01-13 17:19:57 +0000142fn payload_with_an_invalid_initrd_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000143 assert_payload_verification_with_initrd_fails(
Alice Wang5c1a7562023-01-13 17:19:57 +0000144 &load_latest_signed_kernel()?,
145 /*initrd=*/ &fs::read(UNSIGNED_TEST_IMG_PATH)?,
146 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000147 AvbSlotVerifyError::Verification,
Alice Wang5c1a7562023-01-13 17:19:57 +0000148 )
149}
150
151#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000152fn unsigned_kernel_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000153 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000154 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
155 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000156 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000157 AvbSlotVerifyError::Io,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000158 )
159}
160
161#[test]
162fn tampered_kernel_fails_verification() -> Result<()> {
163 let mut kernel = load_latest_signed_kernel()?;
164 kernel[1] = !kernel[1]; // Flip the bits
165
Alice Wang1f0add02023-01-23 16:22:53 +0000166 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000167 &kernel,
168 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000169 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000170 AvbSlotVerifyError::Verification,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000171 )
172}
173
174#[test]
Alice Wangfaceff42023-01-19 09:54:38 +0000175fn kernel_footer_with_vbmeta_offset_overwritten_fails_verification() -> Result<()> {
176 // Arrange.
177 let mut kernel = load_latest_signed_kernel()?;
178 let total_len = kernel.len() as u64;
179 let footer = extract_avb_footer(&kernel)?;
180 assert!(footer.vbmeta_offset < total_len);
181 let vbmeta_offset_addr = ptr::addr_of!(footer.vbmeta_offset) as *const u8;
182 // SAFETY: It is safe as both raw pointers `vbmeta_offset_addr` and `footer` are not null.
183 let vbmeta_offset_start =
184 unsafe { vbmeta_offset_addr.offset_from(ptr::addr_of!(footer) as *const u8) };
185 let footer_start = kernel.len() - size_of::<AvbFooter>();
186 let vbmeta_offset_start = footer_start + usize::try_from(vbmeta_offset_start)?;
187
188 let wrong_offsets = [total_len, u64::MAX];
189 for &wrong_offset in wrong_offsets.iter() {
190 // Act.
191 kernel[vbmeta_offset_start..(vbmeta_offset_start + size_of::<u64>())]
192 .copy_from_slice(&wrong_offset.to_be_bytes());
193
194 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900195 let footer = extract_avb_footer(&kernel)?;
196 // footer is unaligned; copy vbmeta_offset to local variable
197 let vbmeta_offset = footer.vbmeta_offset;
198 assert_eq!(wrong_offset, vbmeta_offset);
Alice Wang1f0add02023-01-23 16:22:53 +0000199 assert_payload_verification_with_initrd_fails(
Alice Wangfaceff42023-01-19 09:54:38 +0000200 &kernel,
201 &load_latest_initrd_normal()?,
202 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000203 AvbSlotVerifyError::Io,
Alice Wangfaceff42023-01-19 09:54:38 +0000204 )?;
205 }
206 Ok(())
207}
208
209#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000210fn tampered_kernel_footer_fails_verification() -> Result<()> {
211 let mut kernel = load_latest_signed_kernel()?;
212 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
213 kernel[avb_footer_index] = !kernel[avb_footer_index];
214
Alice Wang1f0add02023-01-23 16:22:53 +0000215 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000216 &kernel,
217 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000218 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000219 AvbSlotVerifyError::InvalidMetadata,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000220 )
221}
222
Alice Wang58dac082023-01-13 13:03:59 +0000223#[test]
Alice Wang75d05632023-01-25 13:31:18 +0000224fn extended_initrd_fails_verification() -> Result<()> {
225 let mut initrd = load_latest_initrd_normal()?;
226 initrd.extend(b"androidboot.vbmeta.digest=1111");
227
Alice Wang1f0add02023-01-23 16:22:53 +0000228 assert_payload_verification_with_initrd_fails(
Alice Wang75d05632023-01-25 13:31:18 +0000229 &load_latest_signed_kernel()?,
230 &initrd,
231 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000232 AvbSlotVerifyError::Verification,
Alice Wang75d05632023-01-25 13:31:18 +0000233 )
234}
235
236#[test]
Alice Wang58dac082023-01-13 13:03:59 +0000237fn tampered_vbmeta_fails_verification() -> Result<()> {
238 let mut kernel = load_latest_signed_kernel()?;
239 let footer = extract_avb_footer(&kernel)?;
240 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
241
242 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
243
Alice Wang1f0add02023-01-23 16:22:53 +0000244 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000245 &kernel,
246 &load_latest_initrd_normal()?,
247 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000248 AvbSlotVerifyError::InvalidMetadata,
Alice Wang58dac082023-01-13 13:03:59 +0000249 )
250}
251
252#[test]
253fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
254 let mut kernel = load_latest_signed_kernel()?;
255 let footer = extract_avb_footer(&kernel)?;
256 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
257 let public_key_offset = footer.vbmeta_offset as usize
258 + size_of::<AvbVBMetaImageHeader>()
259 + vbmeta_header.authentication_data_block_size as usize
260 + vbmeta_header.public_key_offset as usize;
261 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
262 let empty_public_key = vec![0u8; public_key_size];
263
264 kernel[public_key_offset..(public_key_offset + public_key_size)]
265 .copy_from_slice(&empty_public_key);
266
Alice Wang1f0add02023-01-23 16:22:53 +0000267 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000268 &kernel,
269 &load_latest_initrd_normal()?,
270 &empty_public_key,
Alice Wang1f0add02023-01-23 16:22:53 +0000271 AvbSlotVerifyError::Verification,
Alice Wang58dac082023-01-13 13:03:59 +0000272 )?;
Alice Wang1f0add02023-01-23 16:22:53 +0000273 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000274 &kernel,
275 &load_latest_initrd_normal()?,
276 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000277 AvbSlotVerifyError::Verification,
Alice Wang58dac082023-01-13 13:03:59 +0000278 )
279}
280
Alice Wangf06bfd72023-01-19 09:24:21 +0000281#[test]
282fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
283 // From external/avb/libavb/avb_vbmeta_image.h
284 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
285
286 // Arrange.
287 let mut kernel = load_latest_signed_kernel()?;
288 let footer = extract_avb_footer(&kernel)?;
289 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900290
291 // vbmeta_header is unaligned; copy flags to local variable
292 let vbmeta_header_flags = vbmeta_header.flags;
293 assert_eq!(0, vbmeta_header_flags, "The disable flag should not be set in the latest kernel.");
Alice Wangf06bfd72023-01-19 09:24:21 +0000294 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
295 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
296 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
297 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
298
299 // Act.
300 kernel[flags_offset..(flags_offset + size_of::<u32>())]
301 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
302
303 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900304 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
305 // vbmeta_header is unaligned; copy flags to local variable
306 let vbmeta_header_flags = vbmeta_header.flags;
307 assert_eq!(
308 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header_flags,
309 "VBMeta verification flag should be disabled now."
310 );
Alice Wang1f0add02023-01-23 16:22:53 +0000311 assert_payload_verification_with_initrd_fails(
Alice Wangf06bfd72023-01-19 09:24:21 +0000312 &kernel,
313 &load_latest_initrd_normal()?,
314 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000315 AvbSlotVerifyError::Verification,
Alice Wangf06bfd72023-01-19 09:24:21 +0000316 )
317}