xref: /aosp_15_r20/system/keymint/tests/tests/keyblob_test.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker // Integration test.
16*9860b763SAndroid Build Coastguard Worker #![cfg(soong)]
17*9860b763SAndroid Build Coastguard Worker 
18*9860b763SAndroid Build Coastguard Worker // Explicitly include alloc because macros from `kmr_common` assume it.
19*9860b763SAndroid Build Coastguard Worker extern crate alloc;
20*9860b763SAndroid Build Coastguard Worker 
21*9860b763SAndroid Build Coastguard Worker use kmr_common::{crypto, crypto::Rng, expect_err, keyblob, keyblob::legacy::KeyBlob};
22*9860b763SAndroid Build Coastguard Worker use kmr_crypto_boring::aes::BoringAes;
23*9860b763SAndroid Build Coastguard Worker use kmr_crypto_boring::eq::BoringEq;
24*9860b763SAndroid Build Coastguard Worker use kmr_crypto_boring::hmac::BoringHmac;
25*9860b763SAndroid Build Coastguard Worker use kmr_crypto_boring::rng::BoringRng;
26*9860b763SAndroid Build Coastguard Worker use kmr_wire::{keymint, keymint::KeyParam};
27*9860b763SAndroid Build Coastguard Worker 
28*9860b763SAndroid Build Coastguard Worker #[test]
test_encrypted_keyblob_roundtrip()29*9860b763SAndroid Build Coastguard Worker fn test_encrypted_keyblob_roundtrip() {
30*9860b763SAndroid Build Coastguard Worker     let aes = BoringAes;
31*9860b763SAndroid Build Coastguard Worker     let hmac = BoringHmac;
32*9860b763SAndroid Build Coastguard Worker     let mut rng = BoringRng;
33*9860b763SAndroid Build Coastguard Worker     let mut root_key = crypto::hmac::Key(vec![0u8; 32]);
34*9860b763SAndroid Build Coastguard Worker     rng.fill_bytes(&mut root_key.0);
35*9860b763SAndroid Build Coastguard Worker     let root_key = crypto::OpaqueOr::Explicit(root_key);
36*9860b763SAndroid Build Coastguard Worker     let plaintext_keyblob = keyblob::PlaintextKeyBlob {
37*9860b763SAndroid Build Coastguard Worker         characteristics: vec![keymint::KeyCharacteristics {
38*9860b763SAndroid Build Coastguard Worker             security_level: keymint::SecurityLevel::TrustedEnvironment,
39*9860b763SAndroid Build Coastguard Worker             authorizations: vec![
40*9860b763SAndroid Build Coastguard Worker                 KeyParam::Algorithm(keymint::Algorithm::Aes),
41*9860b763SAndroid Build Coastguard Worker                 KeyParam::BlockMode(keymint::BlockMode::Ecb),
42*9860b763SAndroid Build Coastguard Worker                 KeyParam::Padding(keymint::PaddingMode::None),
43*9860b763SAndroid Build Coastguard Worker             ],
44*9860b763SAndroid Build Coastguard Worker         }],
45*9860b763SAndroid Build Coastguard Worker         key_material: crypto::KeyMaterial::Aes(crypto::aes::Key::Aes128([0u8; 16]).into()),
46*9860b763SAndroid Build Coastguard Worker     };
47*9860b763SAndroid Build Coastguard Worker     let hidden = vec![
48*9860b763SAndroid Build Coastguard Worker         KeyParam::ApplicationId(b"app_id".to_vec()),
49*9860b763SAndroid Build Coastguard Worker         KeyParam::ApplicationData(b"app_data".to_vec()),
50*9860b763SAndroid Build Coastguard Worker     ];
51*9860b763SAndroid Build Coastguard Worker 
52*9860b763SAndroid Build Coastguard Worker     let encrypted_keyblob = keyblob::encrypt(
53*9860b763SAndroid Build Coastguard Worker         keymint::SecurityLevel::TrustedEnvironment,
54*9860b763SAndroid Build Coastguard Worker         None,
55*9860b763SAndroid Build Coastguard Worker         &aes,
56*9860b763SAndroid Build Coastguard Worker         &hmac,
57*9860b763SAndroid Build Coastguard Worker         &mut rng,
58*9860b763SAndroid Build Coastguard Worker         &root_key,
59*9860b763SAndroid Build Coastguard Worker         &[],
60*9860b763SAndroid Build Coastguard Worker         plaintext_keyblob.clone(),
61*9860b763SAndroid Build Coastguard Worker         hidden.clone(),
62*9860b763SAndroid Build Coastguard Worker         keyblob::SlotPurpose::KeyGeneration,
63*9860b763SAndroid Build Coastguard Worker     )
64*9860b763SAndroid Build Coastguard Worker     .unwrap();
65*9860b763SAndroid Build Coastguard Worker 
66*9860b763SAndroid Build Coastguard Worker     let recovered_keyblob =
67*9860b763SAndroid Build Coastguard Worker         keyblob::decrypt(None, &aes, &hmac, &root_key, encrypted_keyblob, hidden).unwrap();
68*9860b763SAndroid Build Coastguard Worker     assert_eq!(plaintext_keyblob, recovered_keyblob);
69*9860b763SAndroid Build Coastguard Worker }
70*9860b763SAndroid Build Coastguard Worker 
71*9860b763SAndroid Build Coastguard Worker #[test]
test_serialize_authenticated_legacy_keyblob()72*9860b763SAndroid Build Coastguard Worker fn test_serialize_authenticated_legacy_keyblob() {
73*9860b763SAndroid Build Coastguard Worker     let hidden = kmr_common::keyblob::legacy::hidden(&[], &[b"SW"]).unwrap();
74*9860b763SAndroid Build Coastguard Worker     let tests = vec![(
75*9860b763SAndroid Build Coastguard Worker         concat!(
76*9860b763SAndroid Build Coastguard Worker             "00", // version
77*9860b763SAndroid Build Coastguard Worker             "02000000",
78*9860b763SAndroid Build Coastguard Worker             "bbbb", // key material
79*9860b763SAndroid Build Coastguard Worker             concat!(
80*9860b763SAndroid Build Coastguard Worker                 "00000000", // no blob data
81*9860b763SAndroid Build Coastguard Worker                 "00000000", // no params
82*9860b763SAndroid Build Coastguard Worker                 "00000000", // zero size of params
83*9860b763SAndroid Build Coastguard Worker             ),
84*9860b763SAndroid Build Coastguard Worker             concat!(
85*9860b763SAndroid Build Coastguard Worker                 "00000000", // no blob data
86*9860b763SAndroid Build Coastguard Worker                 "00000000", // no params
87*9860b763SAndroid Build Coastguard Worker                 "00000000", // zero size of params
88*9860b763SAndroid Build Coastguard Worker             ),
89*9860b763SAndroid Build Coastguard Worker             "0000000000000000", // hmac
90*9860b763SAndroid Build Coastguard Worker         ),
91*9860b763SAndroid Build Coastguard Worker         KeyBlob { key_material: vec![0xbb, 0xbb], hw_enforced: vec![], sw_enforced: vec![] },
92*9860b763SAndroid Build Coastguard Worker     )];
93*9860b763SAndroid Build Coastguard Worker     for (hex_data, want) in tests {
94*9860b763SAndroid Build Coastguard Worker         let mut data = hex::decode(hex_data).unwrap();
95*9860b763SAndroid Build Coastguard Worker 
96*9860b763SAndroid Build Coastguard Worker         // Key blob cannot be deserialized without a correct MAC.
97*9860b763SAndroid Build Coastguard Worker         let hmac = BoringHmac {};
98*9860b763SAndroid Build Coastguard Worker         let result = KeyBlob::deserialize(&hmac, &data, &hidden, BoringEq);
99*9860b763SAndroid Build Coastguard Worker         expect_err!(result, "invalid key blob");
100*9860b763SAndroid Build Coastguard Worker 
101*9860b763SAndroid Build Coastguard Worker         fix_hmac(&mut data, &hidden);
102*9860b763SAndroid Build Coastguard Worker         let got = KeyBlob::deserialize(&hmac, &data, &hidden, BoringEq).unwrap();
103*9860b763SAndroid Build Coastguard Worker         assert_eq!(got, want);
104*9860b763SAndroid Build Coastguard Worker         let new_data = got.serialize(&hmac, &hidden).unwrap();
105*9860b763SAndroid Build Coastguard Worker         assert_eq!(new_data, data);
106*9860b763SAndroid Build Coastguard Worker     }
107*9860b763SAndroid Build Coastguard Worker }
108*9860b763SAndroid Build Coastguard Worker 
109*9860b763SAndroid Build Coastguard Worker #[test]
test_deserialize_authenticated_legacy_keyblob_fail()110*9860b763SAndroid Build Coastguard Worker fn test_deserialize_authenticated_legacy_keyblob_fail() {
111*9860b763SAndroid Build Coastguard Worker     let hidden = kmr_common::keyblob::legacy::hidden(&[], &[b"SW"]).unwrap();
112*9860b763SAndroid Build Coastguard Worker     let tests = vec![
113*9860b763SAndroid Build Coastguard Worker         (
114*9860b763SAndroid Build Coastguard Worker             concat!(
115*9860b763SAndroid Build Coastguard Worker                 "02", // version
116*9860b763SAndroid Build Coastguard Worker                 "02000000",
117*9860b763SAndroid Build Coastguard Worker                 "bbbb", // key material
118*9860b763SAndroid Build Coastguard Worker                 concat!(
119*9860b763SAndroid Build Coastguard Worker                     "00000000", // no blob data
120*9860b763SAndroid Build Coastguard Worker                     "00000000", // no params
121*9860b763SAndroid Build Coastguard Worker                     "00000000", // zero size of params
122*9860b763SAndroid Build Coastguard Worker                 ),
123*9860b763SAndroid Build Coastguard Worker                 concat!(
124*9860b763SAndroid Build Coastguard Worker                     "00000000", // no blob data
125*9860b763SAndroid Build Coastguard Worker                     "00000000", // no params
126*9860b763SAndroid Build Coastguard Worker                     "00000000", // zero size of params
127*9860b763SAndroid Build Coastguard Worker                 ),
128*9860b763SAndroid Build Coastguard Worker                 "0000000000000000", // hmac
129*9860b763SAndroid Build Coastguard Worker             ),
130*9860b763SAndroid Build Coastguard Worker             "unexpected blob version 2",
131*9860b763SAndroid Build Coastguard Worker         ),
132*9860b763SAndroid Build Coastguard Worker         (
133*9860b763SAndroid Build Coastguard Worker             concat!(
134*9860b763SAndroid Build Coastguard Worker                 "00", // version
135*9860b763SAndroid Build Coastguard Worker                 "02000000",
136*9860b763SAndroid Build Coastguard Worker                 "bbbb", // key material
137*9860b763SAndroid Build Coastguard Worker                 concat!(
138*9860b763SAndroid Build Coastguard Worker                     "00000000", // no blob data
139*9860b763SAndroid Build Coastguard Worker                     "00000000", // no params
140*9860b763SAndroid Build Coastguard Worker                     "00000000", // zero size of params
141*9860b763SAndroid Build Coastguard Worker                 ),
142*9860b763SAndroid Build Coastguard Worker                 concat!(
143*9860b763SAndroid Build Coastguard Worker                     "00000000", // no blob data
144*9860b763SAndroid Build Coastguard Worker                     "00000000", // no params
145*9860b763SAndroid Build Coastguard Worker                     "00000000", // zero size of params
146*9860b763SAndroid Build Coastguard Worker                 ),
147*9860b763SAndroid Build Coastguard Worker                 "00",               // bonus byte
148*9860b763SAndroid Build Coastguard Worker                 "0000000000000000", // hmac
149*9860b763SAndroid Build Coastguard Worker             ),
150*9860b763SAndroid Build Coastguard Worker             "extra data (len 1)",
151*9860b763SAndroid Build Coastguard Worker         ),
152*9860b763SAndroid Build Coastguard Worker     ];
153*9860b763SAndroid Build Coastguard Worker     let hmac = BoringHmac {};
154*9860b763SAndroid Build Coastguard Worker     for (hex_data, msg) in tests {
155*9860b763SAndroid Build Coastguard Worker         let mut data = hex::decode(hex_data).unwrap();
156*9860b763SAndroid Build Coastguard Worker         fix_hmac(&mut data, &hidden);
157*9860b763SAndroid Build Coastguard Worker         let result = KeyBlob::deserialize(&hmac, &data, &hidden, BoringEq);
158*9860b763SAndroid Build Coastguard Worker         expect_err!(result, msg);
159*9860b763SAndroid Build Coastguard Worker     }
160*9860b763SAndroid Build Coastguard Worker }
161*9860b763SAndroid Build Coastguard Worker 
162*9860b763SAndroid Build Coastguard Worker #[test]
test_deserialize_authenticated_legacy_keyblob_truncated()163*9860b763SAndroid Build Coastguard Worker fn test_deserialize_authenticated_legacy_keyblob_truncated() {
164*9860b763SAndroid Build Coastguard Worker     let hidden = kmr_common::keyblob::legacy::hidden(&[], &[b"SW"]).unwrap();
165*9860b763SAndroid Build Coastguard Worker     let mut data = hex::decode(concat!(
166*9860b763SAndroid Build Coastguard Worker         "00", // version
167*9860b763SAndroid Build Coastguard Worker         "02000000",
168*9860b763SAndroid Build Coastguard Worker         "bbbb", // key material
169*9860b763SAndroid Build Coastguard Worker         concat!(
170*9860b763SAndroid Build Coastguard Worker             "00000000", // no blob data
171*9860b763SAndroid Build Coastguard Worker             "00000000", // no params
172*9860b763SAndroid Build Coastguard Worker             "00000000", // zero size of params
173*9860b763SAndroid Build Coastguard Worker         ),
174*9860b763SAndroid Build Coastguard Worker         concat!(
175*9860b763SAndroid Build Coastguard Worker             "00000000", // no blob data
176*9860b763SAndroid Build Coastguard Worker             "00000000", // no params
177*9860b763SAndroid Build Coastguard Worker             "00000000", // zero size of params
178*9860b763SAndroid Build Coastguard Worker         ),
179*9860b763SAndroid Build Coastguard Worker         "0000000000000000", // hmac
180*9860b763SAndroid Build Coastguard Worker     ))
181*9860b763SAndroid Build Coastguard Worker     .unwrap();
182*9860b763SAndroid Build Coastguard Worker     fix_hmac(&mut data, &hidden);
183*9860b763SAndroid Build Coastguard Worker     let hmac = BoringHmac {};
184*9860b763SAndroid Build Coastguard Worker     assert!(KeyBlob::deserialize(&hmac, &data, &hidden, BoringEq).is_ok());
185*9860b763SAndroid Build Coastguard Worker 
186*9860b763SAndroid Build Coastguard Worker     for len in 0..data.len() - 1 {
187*9860b763SAndroid Build Coastguard Worker         // Any truncation of this data is invalid.
188*9860b763SAndroid Build Coastguard Worker         assert!(
189*9860b763SAndroid Build Coastguard Worker             KeyBlob::deserialize(&hmac, &data[..len], &hidden, BoringEq).is_err(),
190*9860b763SAndroid Build Coastguard Worker             "deserialize of data[..{}] subset (len={}) unexpectedly succeeded",
191*9860b763SAndroid Build Coastguard Worker             len,
192*9860b763SAndroid Build Coastguard Worker             data.len()
193*9860b763SAndroid Build Coastguard Worker         );
194*9860b763SAndroid Build Coastguard Worker     }
195*9860b763SAndroid Build Coastguard Worker }
196*9860b763SAndroid Build Coastguard Worker 
fix_hmac(data: &mut [u8], hidden: &[KeyParam])197*9860b763SAndroid Build Coastguard Worker fn fix_hmac(data: &mut [u8], hidden: &[KeyParam]) {
198*9860b763SAndroid Build Coastguard Worker     let hmac = BoringHmac {};
199*9860b763SAndroid Build Coastguard Worker     let mac_offset = data.len() - KeyBlob::MAC_LEN;
200*9860b763SAndroid Build Coastguard Worker     let mac = KeyBlob::compute_hmac(&hmac, &data[..mac_offset], hidden).unwrap();
201*9860b763SAndroid Build Coastguard Worker     data[mac_offset..].copy_from_slice(&mac);
202*9860b763SAndroid Build Coastguard Worker }
203