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