blob: a4e890ec283e9d94dbbf93ff715b90618ff4d73e [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
17use anyhow::Result;
18use avb_bindgen::AvbFooter;
19use pvmfw_avb::{verify_payload, AvbSlotVerifyError};
20use std::{fs, mem::size_of};
21
22const MICRODROID_KERNEL_IMG_PATH: &str = "microdroid_kernel";
23const INITRD_NORMAL_IMG_PATH: &str = "microdroid_initrd_normal.img";
Alice Wang4e55dd92023-01-11 10:17:01 +000024const INITRD_DEBUG_IMG_PATH: &str = "microdroid_initrd_debuggable.img";
Alice Wangbf7fadd2023-01-13 12:18:24 +000025const TEST_IMG_WITH_ONE_HASHDESC_PATH: &str = "test_image_with_one_hashdesc.img";
26const UNSIGNED_TEST_IMG_PATH: &str = "unsigned_test.img";
27
28const PUBLIC_KEY_RSA2048_PATH: &str = "data/testkey_rsa2048_pub.bin";
29const PUBLIC_KEY_RSA4096_PATH: &str = "data/testkey_rsa4096_pub.bin";
30const 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<()> {
36 assert_payload_verification_succeeds(
37 &load_latest_signed_kernel()?,
38 &load_latest_initrd_normal()?,
39 &load_trusted_public_key()?,
40 )
41}
Alice Wangbf7fadd2023-01-13 12:18:24 +000042
Alice Wang4e55dd92023-01-11 10:17:01 +000043#[test]
44fn latest_debug_payload_passes_verification() -> Result<()> {
45 assert_payload_verification_succeeds(
46 &load_latest_signed_kernel()?,
47 &load_latest_initrd_debug()?,
48 &load_trusted_public_key()?,
49 )
Alice Wangbf7fadd2023-01-13 12:18:24 +000050}
51
52#[test]
53fn payload_expecting_no_initrd_passes_verification_with_no_initrd() -> Result<()> {
54 let kernel = fs::read(TEST_IMG_WITH_ONE_HASHDESC_PATH)?;
Alice Wang4e55dd92023-01-11 10:17:01 +000055 let public_key = load_trusted_public_key()?;
Alice Wangbf7fadd2023-01-13 12:18:24 +000056
57 assert_eq!(Ok(()), verify_payload(&kernel, None, &public_key));
58 Ok(())
59}
60
61// TODO(b/256148034): Test that kernel with two hashdesc and no initrd fails verification.
62// e.g. payload_expecting_initrd_fails_verification_with_no_initrd
63
64#[test]
65fn payload_with_empty_public_key_fails_verification() -> Result<()> {
66 assert_payload_verification_fails(
67 &load_latest_signed_kernel()?,
68 &load_latest_initrd_normal()?,
69 /*trusted_public_key=*/ &[0u8; 0],
70 AvbSlotVerifyError::PublicKeyRejected,
71 )
72}
73
74#[test]
75fn payload_with_an_invalid_public_key_fails_verification() -> Result<()> {
76 assert_payload_verification_fails(
77 &load_latest_signed_kernel()?,
78 &load_latest_initrd_normal()?,
79 /*trusted_public_key=*/ &[0u8; 512],
80 AvbSlotVerifyError::PublicKeyRejected,
81 )
82}
83
84#[test]
85fn payload_with_a_different_valid_public_key_fails_verification() -> Result<()> {
86 assert_payload_verification_fails(
87 &load_latest_signed_kernel()?,
88 &load_latest_initrd_normal()?,
89 &fs::read(PUBLIC_KEY_RSA2048_PATH)?,
90 AvbSlotVerifyError::PublicKeyRejected,
91 )
92}
93
94#[test]
95fn unsigned_kernel_fails_verification() -> Result<()> {
96 assert_payload_verification_fails(
97 &fs::read(UNSIGNED_TEST_IMG_PATH)?,
98 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +000099 &load_trusted_public_key()?,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000100 AvbSlotVerifyError::Io,
101 )
102}
103
104#[test]
105fn tampered_kernel_fails_verification() -> Result<()> {
106 let mut kernel = load_latest_signed_kernel()?;
107 kernel[1] = !kernel[1]; // Flip the bits
108
109 assert_payload_verification_fails(
110 &kernel,
111 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000112 &load_trusted_public_key()?,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000113 AvbSlotVerifyError::Verification,
114 )
115}
116
117#[test]
118fn tampered_kernel_footer_fails_verification() -> Result<()> {
119 let mut kernel = load_latest_signed_kernel()?;
120 let avb_footer_index = kernel.len() - size_of::<AvbFooter>() + RANDOM_FOOTER_POS;
121 kernel[avb_footer_index] = !kernel[avb_footer_index];
122
123 assert_payload_verification_fails(
124 &kernel,
125 &load_latest_initrd_normal()?,
Alice Wang4e55dd92023-01-11 10:17:01 +0000126 &load_trusted_public_key()?,
Alice Wangbf7fadd2023-01-13 12:18:24 +0000127 AvbSlotVerifyError::InvalidMetadata,
128 )
129}
130
131fn assert_payload_verification_fails(
132 kernel: &[u8],
133 initrd: &[u8],
134 trusted_public_key: &[u8],
135 expected_error: AvbSlotVerifyError,
136) -> Result<()> {
137 assert_eq!(Err(expected_error), verify_payload(kernel, Some(initrd), trusted_public_key));
138 Ok(())
139}
140
Alice Wang4e55dd92023-01-11 10:17:01 +0000141fn assert_payload_verification_succeeds(
142 kernel: &[u8],
143 initrd: &[u8],
144 trusted_public_key: &[u8],
145) -> Result<()> {
146 assert_eq!(Ok(()), verify_payload(kernel, Some(initrd), trusted_public_key));
147 Ok(())
148}
149
Alice Wangbf7fadd2023-01-13 12:18:24 +0000150fn load_latest_signed_kernel() -> Result<Vec<u8>> {
151 Ok(fs::read(MICRODROID_KERNEL_IMG_PATH)?)
152}
153
154fn load_latest_initrd_normal() -> Result<Vec<u8>> {
155 Ok(fs::read(INITRD_NORMAL_IMG_PATH)?)
156}
Alice Wang4e55dd92023-01-11 10:17:01 +0000157
158fn load_latest_initrd_debug() -> Result<Vec<u8>> {
159 Ok(fs::read(INITRD_DEBUG_IMG_PATH)?)
160}
161
162fn load_trusted_public_key() -> Result<Vec<u8>> {
163 Ok(fs::read(PUBLIC_KEY_RSA4096_PATH)?)
164}