blob: 78f274a17a1a294635b136a6a4550fccce581dc2 [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<()> {
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000056 let public_key = load_trusted_public_key()?;
Alice Wang1f0add02023-01-23 16:22:53 +000057 let verified_boot_data = verify_payload(
Alice Wang86383df2023-01-11 10:03:56 +000058 &fs::read(TEST_IMG_WITH_ONE_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000059 /*initrd=*/ None,
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000060 &public_key,
Alice Wang86383df2023-01-11 10:03:56 +000061 )
Alice Wang1f0add02023-01-23 16:22:53 +000062 .map_err(|e| anyhow!("Verification failed. Error: {}", e))?;
63
Pierre-Clément Tosi81ca0802023-02-14 10:41:38 +000064 let kernel_digest = hash(&[&hex::decode("1111")?, &fs::read(UNSIGNED_TEST_IMG_PATH)?]);
Pierre-Clément Tosif58f3a32023-02-02 16:24:23 +000065 let expected_boot_data = VerifiedBootData {
66 debug_level: DebugLevel::None,
67 kernel_digest,
68 initrd_digest: None,
69 public_key: &public_key,
70 };
Pierre-Clément Tosi81ca0802023-02-14 10:41:38 +000071 assert_eq!(expected_boot_data, verified_boot_data);
72
Alice Wang1f0add02023-01-23 16:22:53 +000073 Ok(())
Alice Wangbf7fadd2023-01-13 12:18:24 +000074}
75
Alice Wang86383df2023-01-11 10:03:56 +000076#[test]
Alice Wangf2752862023-01-18 11:51:25 +000077fn payload_with_non_initrd_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000078 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +000079 &fs::read(TEST_IMG_WITH_NON_INITRD_HASHDESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +000080 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +000081 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +000082 AvbSlotVerifyError::InvalidMetadata,
Alice Wangf2752862023-01-18 11:51:25 +000083 )
84}
85
86#[test]
87fn payload_with_non_initrd_descriptor_fails_verification_with_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000088 assert_payload_verification_with_initrd_fails(
Alice Wangf2752862023-01-18 11:51:25 +000089 &fs::read(TEST_IMG_WITH_INITRD_AND_NON_INITRD_DESC_PATH)?,
90 &load_latest_initrd_normal()?,
91 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +000092 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +000093 )
94}
95
96#[test]
97fn payload_with_prop_descriptor_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +000098 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +000099 &fs::read(TEST_IMG_WITH_PROP_DESC_PATH)?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000100 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +0000101 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000102 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +0000103 )
104}
105
106#[test]
107fn payload_expecting_initrd_fails_verification_with_no_initrd() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000108 assert_payload_verification_fails(
Alice Wang86383df2023-01-11 10:03:56 +0000109 &load_latest_signed_kernel()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000110 /*initrd=*/ None,
Alice Wang86383df2023-01-11 10:03:56 +0000111 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000112 AvbSlotVerifyError::InvalidMetadata,
Alice Wang86383df2023-01-11 10:03:56 +0000113 )
114}
Alice Wangbf7fadd2023-01-13 12:18:24 +0000115
116#[test]
117fn payload_with_empty_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000118 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000119 &load_latest_signed_kernel()?,
120 &load_latest_initrd_normal()?,
121 /*trusted_public_key=*/ &[0u8; 0],
Alice Wang1f0add02023-01-23 16:22:53 +0000122 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000123 )
124}
125
126#[test]
127fn payload_with_an_invalid_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000128 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000129 &load_latest_signed_kernel()?,
130 &load_latest_initrd_normal()?,
131 /*trusted_public_key=*/ &[0u8; 512],
Alice Wang1f0add02023-01-23 16:22:53 +0000132 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000133 )
134}
135
136#[test]
137fn payload_with_a_different_valid_public_key_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000138 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000139 &load_latest_signed_kernel()?,
140 &load_latest_initrd_normal()?,
141 &fs::read(PUBLIC_KEY_RSA2048_PATH)?,
Alice Wang1f0add02023-01-23 16:22:53 +0000142 AvbSlotVerifyError::PublicKeyRejected,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000143 )
144}
145
146#[test]
Alice Wang5c1a7562023-01-13 17:19:57 +0000147fn payload_with_an_invalid_initrd_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000148 assert_payload_verification_with_initrd_fails(
Alice Wang5c1a7562023-01-13 17:19:57 +0000149 &load_latest_signed_kernel()?,
150 /*initrd=*/ &fs::read(UNSIGNED_TEST_IMG_PATH)?,
151 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000152 AvbSlotVerifyError::Verification,
Alice Wang5c1a7562023-01-13 17:19:57 +0000153 )
154}
155
156#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000157fn unsigned_kernel_fails_verification() -> Result<()> {
Alice Wang1f0add02023-01-23 16:22:53 +0000158 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000159 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
160 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000161 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000162 AvbSlotVerifyError::Io,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000163 )
164}
165
166#[test]
167fn tampered_kernel_fails_verification() -> Result<()> {
168 let mut kernel = load_latest_signed_kernel()?;
169 kernel[1] = !kernel[1]; // Flip the bits
170
Alice Wang1f0add02023-01-23 16:22:53 +0000171 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000172 &kernel,
173 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000174 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000175 AvbSlotVerifyError::Verification,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000176 )
177}
178
179#[test]
Alice Wangfaceff42023-01-19 09:54:38 +0000180fn kernel_footer_with_vbmeta_offset_overwritten_fails_verification() -> Result<()> {
181 // Arrange.
182 let mut kernel = load_latest_signed_kernel()?;
183 let total_len = kernel.len() as u64;
184 let footer = extract_avb_footer(&kernel)?;
185 assert!(footer.vbmeta_offset < total_len);
186 let vbmeta_offset_addr = ptr::addr_of!(footer.vbmeta_offset) as *const u8;
187 // SAFETY: It is safe as both raw pointers `vbmeta_offset_addr` and `footer` are not null.
188 let vbmeta_offset_start =
189 unsafe { vbmeta_offset_addr.offset_from(ptr::addr_of!(footer) as *const u8) };
190 let footer_start = kernel.len() - size_of::<AvbFooter>();
191 let vbmeta_offset_start = footer_start + usize::try_from(vbmeta_offset_start)?;
192
193 let wrong_offsets = [total_len, u64::MAX];
194 for &wrong_offset in wrong_offsets.iter() {
195 // Act.
196 kernel[vbmeta_offset_start..(vbmeta_offset_start + size_of::<u64>())]
197 .copy_from_slice(&wrong_offset.to_be_bytes());
198
199 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900200 let footer = extract_avb_footer(&kernel)?;
201 // footer is unaligned; copy vbmeta_offset to local variable
202 let vbmeta_offset = footer.vbmeta_offset;
203 assert_eq!(wrong_offset, vbmeta_offset);
Alice Wang1f0add02023-01-23 16:22:53 +0000204 assert_payload_verification_with_initrd_fails(
Alice Wangfaceff42023-01-19 09:54:38 +0000205 &kernel,
206 &load_latest_initrd_normal()?,
207 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000208 AvbSlotVerifyError::Io,
Alice Wangfaceff42023-01-19 09:54:38 +0000209 )?;
210 }
211 Ok(())
212}
213
214#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000215fn tampered_kernel_footer_fails_verification() -> Result<()> {
216 let mut kernel = load_latest_signed_kernel()?;
217 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
218 kernel[avb_footer_index] = !kernel[avb_footer_index];
219
Alice Wang1f0add02023-01-23 16:22:53 +0000220 assert_payload_verification_with_initrd_fails(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000221 &kernel,
222 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000223 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000224 AvbSlotVerifyError::InvalidMetadata,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000225 )
226}
227
Alice Wang58dac082023-01-13 13:03:59 +0000228#[test]
Alice Wang75d05632023-01-25 13:31:18 +0000229fn extended_initrd_fails_verification() -> Result<()> {
230 let mut initrd = load_latest_initrd_normal()?;
231 initrd.extend(b"androidboot.vbmeta.digest=1111");
232
Alice Wang1f0add02023-01-23 16:22:53 +0000233 assert_payload_verification_with_initrd_fails(
Alice Wang75d05632023-01-25 13:31:18 +0000234 &load_latest_signed_kernel()?,
235 &initrd,
236 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000237 AvbSlotVerifyError::Verification,
Alice Wang75d05632023-01-25 13:31:18 +0000238 )
239}
240
241#[test]
Alice Wang58dac082023-01-13 13:03:59 +0000242fn tampered_vbmeta_fails_verification() -> Result<()> {
243 let mut kernel = load_latest_signed_kernel()?;
244 let footer = extract_avb_footer(&kernel)?;
245 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
246
247 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
248
Alice Wang1f0add02023-01-23 16:22:53 +0000249 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000250 &kernel,
251 &load_latest_initrd_normal()?,
252 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000253 AvbSlotVerifyError::InvalidMetadata,
Alice Wang58dac082023-01-13 13:03:59 +0000254 )
255}
256
257#[test]
258fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
259 let mut kernel = load_latest_signed_kernel()?;
260 let footer = extract_avb_footer(&kernel)?;
261 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
262 let public_key_offset = footer.vbmeta_offset as usize
263 + size_of::<AvbVBMetaImageHeader>()
264 + vbmeta_header.authentication_data_block_size as usize
265 + vbmeta_header.public_key_offset as usize;
266 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
267 let empty_public_key = vec![0u8; public_key_size];
268
269 kernel[public_key_offset..(public_key_offset + public_key_size)]
270 .copy_from_slice(&empty_public_key);
271
Alice Wang1f0add02023-01-23 16:22:53 +0000272 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000273 &kernel,
274 &load_latest_initrd_normal()?,
275 &empty_public_key,
Alice Wang1f0add02023-01-23 16:22:53 +0000276 AvbSlotVerifyError::Verification,
Alice Wang58dac082023-01-13 13:03:59 +0000277 )?;
Alice Wang1f0add02023-01-23 16:22:53 +0000278 assert_payload_verification_with_initrd_fails(
Alice Wang58dac082023-01-13 13:03:59 +0000279 &kernel,
280 &load_latest_initrd_normal()?,
281 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000282 AvbSlotVerifyError::Verification,
Alice Wang58dac082023-01-13 13:03:59 +0000283 )
284}
285
Alice Wangf06bfd72023-01-19 09:24:21 +0000286#[test]
287fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
288 // From external/avb/libavb/avb_vbmeta_image.h
289 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
290
291 // Arrange.
292 let mut kernel = load_latest_signed_kernel()?;
293 let footer = extract_avb_footer(&kernel)?;
294 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900295
296 // vbmeta_header is unaligned; copy flags to local variable
297 let vbmeta_header_flags = vbmeta_header.flags;
298 assert_eq!(0, vbmeta_header_flags, "The disable flag should not be set in the latest kernel.");
Alice Wangf06bfd72023-01-19 09:24:21 +0000299 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
300 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
301 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
302 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
303
304 // Act.
305 kernel[flags_offset..(flags_offset + size_of::<u32>())]
306 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
307
308 // Assert.
Inseob Kim8ebf1da2023-01-27 18:12:57 +0900309 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
310 // vbmeta_header is unaligned; copy flags to local variable
311 let vbmeta_header_flags = vbmeta_header.flags;
312 assert_eq!(
313 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header_flags,
314 "VBMeta verification flag should be disabled now."
315 );
Alice Wang1f0add02023-01-23 16:22:53 +0000316 assert_payload_verification_with_initrd_fails(
Alice Wangf06bfd72023-01-19 09:24:21 +0000317 &kernel,
318 &load_latest_initrd_normal()?,
319 &load_trusted_public_key()?,
Alice Wang1f0add02023-01-23 16:22:53 +0000320 AvbSlotVerifyError::Verification,
Alice Wangf06bfd72023-01-19 09:24:21 +0000321 )
322}