blob: 6b98dfb4207e5b6f25cde37ef67ea670c9c96932 [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};
21use pvmfw_avb::AvbSlotVerifyError;
22use 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 Wang2925b0a2023-01-19 10:44:24 +000040 Ok(()),
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 Wang2925b0a2023-01-19 10:44:24 +000050 Ok(()),
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()?,
60 Ok(()),
61 )
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()?,
70 Ok(()),
71 )
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]
125fn unsigned_kernel_fails_verification() -> Result<()> {
Alice Wang2925b0a2023-01-19 10:44:24 +0000126 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000127 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
128 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000129 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000130 Err(AvbSlotVerifyError::Io),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000131 )
132}
133
134#[test]
135fn tampered_kernel_fails_verification() -> Result<()> {
136 let mut kernel = load_latest_signed_kernel()?;
137 kernel[1] = !kernel[1]; // Flip the bits
138
Alice Wang2925b0a2023-01-19 10:44:24 +0000139 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000140 &kernel,
141 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000142 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000143 Err(AvbSlotVerifyError::Verification),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000144 )
145}
146
147#[test]
Alice Wangfaceff42023-01-19 09:54:38 +0000148fn kernel_footer_with_vbmeta_offset_overwritten_fails_verification() -> Result<()> {
149 // Arrange.
150 let mut kernel = load_latest_signed_kernel()?;
151 let total_len = kernel.len() as u64;
152 let footer = extract_avb_footer(&kernel)?;
153 assert!(footer.vbmeta_offset < total_len);
154 let vbmeta_offset_addr = ptr::addr_of!(footer.vbmeta_offset) as *const u8;
155 // SAFETY: It is safe as both raw pointers `vbmeta_offset_addr` and `footer` are not null.
156 let vbmeta_offset_start =
157 unsafe { vbmeta_offset_addr.offset_from(ptr::addr_of!(footer) as *const u8) };
158 let footer_start = kernel.len() - size_of::<AvbFooter>();
159 let vbmeta_offset_start = footer_start + usize::try_from(vbmeta_offset_start)?;
160
161 let wrong_offsets = [total_len, u64::MAX];
162 for &wrong_offset in wrong_offsets.iter() {
163 // Act.
164 kernel[vbmeta_offset_start..(vbmeta_offset_start + size_of::<u64>())]
165 .copy_from_slice(&wrong_offset.to_be_bytes());
166
167 // Assert.
168 let footer = extract_avb_footer(&kernel)?;
169 assert_eq!(wrong_offset, footer.vbmeta_offset as u64);
170 assert_payload_verification_with_initrd_eq(
171 &kernel,
172 &load_latest_initrd_normal()?,
173 &load_trusted_public_key()?,
174 Err(AvbSlotVerifyError::Io),
175 )?;
176 }
177 Ok(())
178}
179
180#[test]
Alice Wangbf7fadd2023-01-13 12:18:24 +0000181fn tampered_kernel_footer_fails_verification() -> Result<()> {
182 let mut kernel = load_latest_signed_kernel()?;
183 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
184 kernel[avb_footer_index] = !kernel[avb_footer_index];
185
Alice Wang2925b0a2023-01-19 10:44:24 +0000186 assert_payload_verification_with_initrd_eq(
Alice Wangbf7fadd2023-01-13 12:18:24 +0000187 &kernel,
188 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000189 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000190 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wangbf7fadd2023-01-13 12:18:24 +0000191 )
192}
193
Alice Wang58dac082023-01-13 13:03:59 +0000194#[test]
195fn tampered_vbmeta_fails_verification() -> Result<()> {
196 let mut kernel = load_latest_signed_kernel()?;
197 let footer = extract_avb_footer(&kernel)?;
198 let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
199
200 kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
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 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000206 Err(AvbSlotVerifyError::InvalidMetadata),
Alice Wang58dac082023-01-13 13:03:59 +0000207 )
208}
209
210#[test]
211fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
212 let mut kernel = load_latest_signed_kernel()?;
213 let footer = extract_avb_footer(&kernel)?;
214 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
215 let public_key_offset = footer.vbmeta_offset as usize
216 + size_of::<AvbVBMetaImageHeader>()
217 + vbmeta_header.authentication_data_block_size as usize
218 + vbmeta_header.public_key_offset as usize;
219 let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
220 let empty_public_key = vec![0u8; public_key_size];
221
222 kernel[public_key_offset..(public_key_offset + public_key_size)]
223 .copy_from_slice(&empty_public_key);
224
Alice Wang2925b0a2023-01-19 10:44:24 +0000225 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000226 &kernel,
227 &load_latest_initrd_normal()?,
228 &empty_public_key,
Alice Wang2925b0a2023-01-19 10:44:24 +0000229 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000230 )?;
Alice Wang2925b0a2023-01-19 10:44:24 +0000231 assert_payload_verification_with_initrd_eq(
Alice Wang58dac082023-01-13 13:03:59 +0000232 &kernel,
233 &load_latest_initrd_normal()?,
234 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000235 Err(AvbSlotVerifyError::Verification),
Alice Wang58dac082023-01-13 13:03:59 +0000236 )
237}
238
Alice Wangf06bfd72023-01-19 09:24:21 +0000239#[test]
240fn vbmeta_with_verification_flag_disabled_fails_verification() -> Result<()> {
241 // From external/avb/libavb/avb_vbmeta_image.h
242 const AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: u32 = 2;
243
244 // Arrange.
245 let mut kernel = load_latest_signed_kernel()?;
246 let footer = extract_avb_footer(&kernel)?;
247 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
248 assert_eq!(
249 0, vbmeta_header.flags as u32,
250 "The disable flag should not be set in the latest kernel."
251 );
252 let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
253 // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
254 let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
255 let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
256
257 // Act.
258 kernel[flags_offset..(flags_offset + size_of::<u32>())]
259 .copy_from_slice(&AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.to_be_bytes());
260
261 // Assert.
262 let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
263 assert_eq!(
264 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, vbmeta_header.flags as u32,
265 "VBMeta verification flag should be disabled now."
266 );
Alice Wang2925b0a2023-01-19 10:44:24 +0000267 assert_payload_verification_with_initrd_eq(
Alice Wangf06bfd72023-01-19 09:24:21 +0000268 &kernel,
269 &load_latest_initrd_normal()?,
270 &load_trusted_public_key()?,
Alice Wang2925b0a2023-01-19 10:44:24 +0000271 Err(AvbSlotVerifyError::Verification),
Alice Wangf06bfd72023-01-19 09:24:21 +0000272 )
273}