1 /*
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 //! Module used to interact with keymint secure storage data.
17 use crate::keybox;
18 use crate::keymaster_attributes;
19 use alloc::{format, string::String, vec::Vec};
20 use keymaster_attributes::UdsCerts;
21 use kmr_common::{
22 crypto::{self, KeyMaterial},
23 km_err, try_to_vec, vec_try, vec_try_with_capacity,
24 wire::keymint,
25 wire::AttestationIdInfo,
26 Error,
27 };
28 use kmr_ta::device::{
29 RetrieveAttestationIds, RetrieveCertSigningInfo, SigningAlgorithm, SigningKeyType,
30 };
31 use log::{error, info};
32 use protobuf::{self, Message};
33 use storage::{OpenMode, Port, SecureFile, Session};
34
35 #[cfg(feature = "soft_attestation_fallback")]
36 mod software;
37
38 /// Name of file holding attestation device ID information; matches the `kAttestationIdsFileName`
39 /// value in `secure_storage_manager.cpp` for back-compatibility.
40 const KM_ATTESTATION_ID_FILENAME: &str = "AttestationIds";
41
42 /// Filename prefix for files holding attestation keys and certificates; matches the
43 /// `kAttestKeyCertPrefix` value in `secure_storage_manager.cpp` for back-compatibility.
44 const KM_ATTESTATION_KEY_CERT_PREFIX: &str = "AttestKeyCert";
45
46 /// Filename for holding UDS Certificate.
47 const KM_RKP_UDS_CERT_FILENAME: &str = "UdsCerts";
48
49 /// Maximum size of each attestation certificate
50 const MAX_CERT_SIZE: usize = 2048;
51 /// Maximum number of attestation certificates
52 const MAX_CERT_CHAIN_LEN: usize = 3;
53
54 /// Maximum number of UDS certificates
55 const MAX_UDS_CERT_CHAIN_LEN: usize = 3;
56
57 /// Return the filename for the file holding attestation keys and certificates for the specified
58 /// signing algorithm.
get_key_slot_file_name(algorithm: SigningAlgorithm) -> String59 fn get_key_slot_file_name(algorithm: SigningAlgorithm) -> String {
60 let suffix = match algorithm {
61 SigningAlgorithm::Ec => "ec",
62 SigningAlgorithm::Rsa => "rsa",
63 };
64 format!("{}.{}", KM_ATTESTATION_KEY_CERT_PREFIX, suffix)
65 }
66
67 // `session` and `secure_file` are of type `Option` because close() takes self by value, so this was
68 // needed for the `Drop` implementation. The intent though is that they should always be populated
69 // on a OpenSecureFile object; which is `OpenSecureFile::new` behavior.
70 struct OpenSecureFile {
71 session: Option<Session>,
72 secure_file: Option<SecureFile>,
73 }
74
75 impl OpenSecureFile {
76 /// Opens a secure storage session and creates the requested file
new(file_name: &str) -> Result<Self, Error>77 fn new(file_name: &str) -> Result<Self, Error> {
78 let mut session = Session::new(Port::TamperProof, true).map_err(|e| {
79 km_err!(SecureHwCommunicationFailed, "couldn't create storage session: {:?}", e)
80 })?;
81 let secure_file = session.open_file(file_name, OpenMode::Create).map_err(|e| {
82 km_err!(SecureHwCommunicationFailed, "couldn't create file {}: {:?}", file_name, e)
83 })?;
84 Ok(OpenSecureFile { session: Some(session), secure_file: Some(secure_file) })
85 }
86
87 /// Writes provided data in the previously opened file
write_all(&mut self, data: &[u8]) -> Result<(), Error>88 fn write_all(&mut self, data: &[u8]) -> Result<(), Error> {
89 // Even though we are handling the case when secure_file and session are None, this is not
90 // expected; if an OpenSecureFile object exists its `secure_file` and `session` elements
91 // shall be populated.
92 let session =
93 self.session.as_mut().ok_or(km_err!(UnknownError, "session shouldn't ever be None"))?;
94 let file = self
95 .secure_file
96 .as_mut()
97 .ok_or(km_err!(UnknownError, "secure_file shouldn't ever be None"))?;
98 session.write_all(file, data).map_err(|e| {
99 km_err!(SecureHwCommunicationFailed, "failed to write data; received error: {:?}", e)
100 })
101 }
102
103 /// Close the session and file handlers by taking ownership and letting the value be dropped
104 #[cfg(test)]
close(self)105 fn close(self) {}
106 }
107
108 impl Drop for OpenSecureFile {
drop(&mut self)109 fn drop(&mut self) {
110 // Even though we are handling the case when secure_file and session are None, this is not
111 // expected; if an OpenSecureFile object exists its `secure_file` and `session` elements
112 // shall be populated.
113 if let Some(file) = self.secure_file.take() {
114 file.close();
115 }
116 if let Some(session) = self.session.take() {
117 session.close();
118 }
119 }
120 }
121
122 /// Creates an empty attestation IDs file
create_attestation_id_file() -> Result<OpenSecureFile, Error>123 fn create_attestation_id_file() -> Result<OpenSecureFile, Error> {
124 OpenSecureFile::new(KM_ATTESTATION_ID_FILENAME)
125 }
126
127 /// Creates and empty attestation key/certificates file for the given algorithm
create_attestation_key_file(algorithm: SigningAlgorithm) -> Result<OpenSecureFile, Error>128 fn create_attestation_key_file(algorithm: SigningAlgorithm) -> Result<OpenSecureFile, Error> {
129 let file_name = get_key_slot_file_name(algorithm);
130 OpenSecureFile::new(&file_name)
131 }
132
write_protobuf_to_attestation_key_file( algorithm: SigningAlgorithm, attestation_key_data: keymaster_attributes::AttestationKey, ) -> Result<(), Error>133 fn write_protobuf_to_attestation_key_file(
134 algorithm: SigningAlgorithm,
135 attestation_key_data: keymaster_attributes::AttestationKey,
136 ) -> Result<(), Error> {
137 let serialized_buffer = attestation_key_data.write_to_bytes().map_err(|e| {
138 km_err!(SecureHwCommunicationFailed, "couldn't serialize attestationKey: {:?}", e)
139 })?;
140 let mut file = create_attestation_key_file(algorithm)?;
141 file.write_all(&serialized_buffer).map_err(|e| {
142 km_err!(SecureHwCommunicationFailed, "failed to provision attestation key file: {:?}", e)
143 })?;
144 Ok(())
145 }
146
147 /// Unwraps a keybox wrapped key and uses it to provision the key on the device.
set_wrapped_attestation_key( algorithm: SigningAlgorithm, key_data: &[u8], ) -> Result<(), Error>148 pub(crate) fn set_wrapped_attestation_key(
149 algorithm: SigningAlgorithm,
150 key_data: &[u8],
151 ) -> Result<(), Error> {
152 let unwrapped_key = keybox::keybox_unwrap(key_data)?;
153 provision_attestation_key_file(algorithm, &unwrapped_key)
154 }
155
156 /// Tries to read the file containing the attestation key and certificates and only replaces the key
157 /// section. If the file doesn't exist it will create it and save the provided key.
provision_attestation_key_file( algorithm: SigningAlgorithm, key_data: &[u8], ) -> Result<(), Error>158 pub(crate) fn provision_attestation_key_file(
159 algorithm: SigningAlgorithm,
160 key_data: &[u8],
161 ) -> Result<(), Error> {
162 let mut attestation_key = read_attestation_key_content(algorithm)?;
163 attestation_key.set_key(try_to_vec(key_data)?);
164
165 write_protobuf_to_attestation_key_file(algorithm, attestation_key)
166 }
167
168 /// Creates and empty UDS certificates file
create_uds_cert_file() -> Result<OpenSecureFile, Error>169 fn create_uds_cert_file() -> Result<OpenSecureFile, Error> {
170 OpenSecureFile::new(KM_RKP_UDS_CERT_FILENAME)
171 }
172
173 /// Delete the existing UDS certificates file
delete_uds_cert_file() -> Result<(), Error>174 fn delete_uds_cert_file() -> Result<(), Error> {
175 let mut session = Session::new(Port::TamperProof, true).map_err(|e| {
176 km_err!(SecureHwCommunicationFailed, "failed to connect to storage port: {:?}", e)
177 })?;
178 session.remove(KM_RKP_UDS_CERT_FILENAME).map_err(|e| {
179 km_err!(
180 SecureHwCommunicationFailed,
181 "failed to delete {:?}: {:?}",
182 KM_RKP_UDS_CERT_FILENAME,
183 e
184 )
185 })?;
186 Ok(())
187 }
188
write_protobuf_to_uds_cert_file(uds_cert_pb: UdsCerts) -> Result<(), Error>189 fn write_protobuf_to_uds_cert_file(uds_cert_pb: UdsCerts) -> Result<(), Error> {
190 let serialized_buffer = uds_cert_pb.write_to_bytes().map_err(|e| {
191 km_err!(SecureHwCommunicationFailed, "couldn't serialize UdsCerts: {:?}", e)
192 })?;
193
194 let mut file = create_uds_cert_file()?;
195 file.write_all(&serialized_buffer).map_err(|e| {
196 km_err!(SecureHwCommunicationFailed, "failed to provision UdsCerts file: {:?}", e)
197 })?;
198 Ok(())
199 }
200
201 /// Tries to read the file containing the UdsCerts and append a cert on it.
202 /// If the file doesn't exist it will create it and save the provided key.
append_uds_cert_chain(cert_data: &[u8]) -> Result<(), Error>203 pub(crate) fn append_uds_cert_chain(cert_data: &[u8]) -> Result<(), Error> {
204 if cert_data.is_empty() || cert_data.len() > MAX_CERT_SIZE {
205 return Err(km_err!(
206 InvalidArgument,
207 "Invalid certificate size: {}, max size {}",
208 cert_data.len(),
209 MAX_CERT_SIZE
210 ));
211 }
212
213 let mut uds_cert_pb = read_uds_cert_content()?;
214 let cert_chain_len = uds_cert_pb.get_certs().len();
215 if cert_chain_len >= MAX_UDS_CERT_CHAIN_LEN {
216 return Err(km_err!(
217 InvalidArgument,
218 "cannot accept more certificates, {} already provisioned",
219 cert_chain_len
220 ));
221 }
222
223 let mut cert = keymaster_attributes::AttestationCert::new();
224 cert.set_content(try_to_vec(cert_data)?);
225 uds_cert_pb.mut_certs().push(cert);
226
227 write_protobuf_to_uds_cert_file(uds_cert_pb)
228 }
229
230 /// Tries to read the file containing the attestation key and certificates and adds a certificate to
231 /// it if there is still space left on the certificate section. If the file doesn't exist it will
232 /// create it and save the provided certificate.
append_attestation_cert_chain( algorithm: SigningAlgorithm, cert_data: &[u8], ) -> Result<(), Error>233 pub(crate) fn append_attestation_cert_chain(
234 algorithm: SigningAlgorithm,
235 cert_data: &[u8],
236 ) -> Result<(), Error> {
237 if cert_data.is_empty() {
238 return Err(km_err!(InvalidInputLength, "received a certificate of length 0"));
239 }
240
241 if cert_data.len() > MAX_CERT_SIZE {
242 return Err(km_err!(
243 InvalidArgument,
244 "certificate is too big. Size: {}, max size {}",
245 cert_data.len(),
246 MAX_CERT_SIZE
247 ));
248 }
249
250 let mut attestation_key_data = read_attestation_key_content(algorithm)?;
251 let cert_chain_len = attestation_key_data.get_certs().len();
252
253 if cert_chain_len >= MAX_CERT_CHAIN_LEN {
254 return Err(km_err!(
255 InvalidArgument,
256 "cannot accept more certificates, {} already provisioned",
257 cert_chain_len
258 ));
259 }
260
261 let mut cert = keymaster_attributes::AttestationCert::new();
262 cert.set_content(try_to_vec(cert_data)?);
263 attestation_key_data.mut_certs().push(cert);
264
265 write_protobuf_to_attestation_key_file(algorithm, attestation_key_data)
266 }
267
268 /// Tries to read the file containing the UdsCert. It's fine if that file is clear, or will try to
269 /// delete it. After this call, all "read" operation will get a default <UdsCerts> object.
maybe_delete_uds_cert_chain() -> Result<(), Error>270 pub(crate) fn maybe_delete_uds_cert_chain() -> Result<(), Error> {
271 let mut uds_cert_pb = read_uds_cert_content()?;
272 if uds_cert_pb.get_certs().is_empty() {
273 // No certs found, nothing to delete.
274 return Ok(());
275 }
276 delete_uds_cert_file()?;
277 uds_cert_pb = read_uds_cert_content()?;
278 let cert_chain_len = uds_cert_pb.get_certs().len();
279 if cert_chain_len != 0 {
280 return Err(km_err!(
281 UnknownError,
282 "couldn't delete all certificates, found {}",
283 cert_chain_len
284 ));
285 }
286 Ok(())
287 }
288
289 /// Tries to read the file containing the attestation key delete only the certificate section.
clear_attestation_cert_chain(algorithm: SigningAlgorithm) -> Result<(), Error>290 pub(crate) fn clear_attestation_cert_chain(algorithm: SigningAlgorithm) -> Result<(), Error> {
291 let mut attestation_key_data = read_attestation_key_content(algorithm)?;
292 if attestation_key_data.get_certs().is_empty() {
293 // No certs found, nothing to delete.
294 return Ok(());
295 }
296 attestation_key_data.clear_certs();
297 write_protobuf_to_attestation_key_file(algorithm, attestation_key_data)?;
298 // Checking that the certificates were indeed deleted
299 let attestation_key_data = read_attestation_key_content(algorithm)?;
300 let cert_chain_len = attestation_key_data.get_certs().len();
301 if cert_chain_len != 0 {
302 error!("Couldn't delete all certificates, found {}", cert_chain_len);
303 return Err(km_err!(
304 UnknownError,
305 "couldn't delete all certificates, found {}",
306 cert_chain_len
307 ));
308 }
309 Ok(())
310 }
311
312 /// Creates a new attestation IDs file and saves the provided data there
313 #[allow(clippy::too_many_arguments)]
provision_attestation_id_file( brand: &[u8], product: &[u8], device: &[u8], serial: &[u8], imei: &[u8], meid: &[u8], manufacturer: &[u8], model: &[u8], maybe_imei2: Option<&[u8]>, ) -> Result<(), Error>314 pub(crate) fn provision_attestation_id_file(
315 brand: &[u8],
316 product: &[u8],
317 device: &[u8],
318 serial: &[u8],
319 imei: &[u8],
320 meid: &[u8],
321 manufacturer: &[u8],
322 model: &[u8],
323 maybe_imei2: Option<&[u8]>,
324 ) -> Result<(), Error> {
325 let mut file = create_attestation_id_file()?;
326
327 let mut attestation_ids = keymaster_attributes::AttestationIds::new();
328
329 if !brand.is_empty() {
330 attestation_ids.set_brand(try_to_vec(brand)?);
331 }
332 if !device.is_empty() {
333 attestation_ids.set_device(try_to_vec(device)?);
334 }
335 if !product.is_empty() {
336 attestation_ids.set_product(try_to_vec(product)?);
337 }
338 if !serial.is_empty() {
339 attestation_ids.set_serial(try_to_vec(serial)?);
340 }
341 if !imei.is_empty() {
342 attestation_ids.set_imei(try_to_vec(imei)?);
343 }
344 if !meid.is_empty() {
345 attestation_ids.set_meid(try_to_vec(meid)?);
346 }
347 if !manufacturer.is_empty() {
348 attestation_ids.set_manufacturer(try_to_vec(manufacturer)?);
349 }
350 if !model.is_empty() {
351 attestation_ids.set_model(try_to_vec(model)?);
352 }
353 match maybe_imei2 {
354 Some(imei2) if !imei2.is_empty() => {
355 attestation_ids.set_second_imei(try_to_vec(imei2)?);
356 }
357 _ => (),
358 }
359
360 let serialized_buffer = attestation_ids.write_to_bytes().map_err(|e| {
361 km_err!(SecureHwCommunicationFailed, "couldn't serialize attestationIds: {:?}", e)
362 })?;
363
364 file.write_all(&serialized_buffer).map_err(|e| {
365 km_err!(SecureHwCommunicationFailed, "failed to provision attestation IDs file: {:?}", e)
366 })?;
367
368 Ok(())
369 }
370
371 /// Delete all attestation IDs from secure storage.
delete_attestation_ids() -> Result<(), Error>372 pub(crate) fn delete_attestation_ids() -> Result<(), Error> {
373 let mut session = Session::new(Port::TamperProof, true).map_err(|e| {
374 km_err!(SecureHwCommunicationFailed, "failed to connect to storage port: {:?}", e)
375 })?;
376 session.remove(KM_ATTESTATION_ID_FILENAME).map_err(|e| {
377 km_err!(SecureHwCommunicationFailed, "failed to delete attestation IDs file: {:?}", e)
378 })?;
379 Ok(())
380 }
381
382 /// Return the contents of the specified file in secure storage.
get_file_contents(file_name: &str) -> Result<Option<Vec<u8>>, Error>383 fn get_file_contents(file_name: &str) -> Result<Option<Vec<u8>>, Error> {
384 let mut session = Session::new(Port::TamperProof, true).map_err(|e| {
385 km_err!(SecureHwCommunicationFailed, "failed to connect to storage port: {:?}", e)
386 })?;
387 // Distinguishing between file not found and other errors, so we can match c++ behavior when
388 // retrieving attestation IDs on unprovisioned devices.
389 let file = match session.open_file(file_name, OpenMode::Open) {
390 Ok(file) => file,
391 Err(storage::Error::Code(trusty_sys::Error::NotFound)) => {
392 info!("{file_name:?} NotFound");
393 return Ok(None);
394 }
395 Err(e) => {
396 return Err(km_err!(
397 SecureHwCommunicationFailed,
398 "failed to open '{}': {:?}",
399 file_name,
400 e
401 ));
402 }
403 };
404 let size = session.get_size(&file).map_err(|e| {
405 km_err!(SecureHwCommunicationFailed, "failed to get size for '{}': {:?}", file_name, e)
406 })?;
407 let mut buffer = vec_try![0; size]?;
408 let content = session.read_all(&file, buffer.as_mut_slice()).map_err(|e| {
409 km_err!(SecureHwCommunicationFailed, "failed to read '{}': {:?}", file_name, e)
410 })?;
411 let total_size = content.len();
412 buffer.resize(total_size, 0);
413 Ok(Some(buffer))
414 }
415
416 /// Retrieve the attestation ID information from secure storage.
read_attestation_ids() -> Result<AttestationIdInfo, Error>417 pub(crate) fn read_attestation_ids() -> Result<AttestationIdInfo, Error> {
418 // Retrieving attestation IDs from file. If the file is not found (device not provisioned) we
419 // will return an empty AttestationIdInfo info to match the c++ code behavior
420 let content = match get_file_contents(KM_ATTESTATION_ID_FILENAME) {
421 Ok(Some(file_contents)) => file_contents,
422 Ok(None) => return Ok(AttestationIdInfo::default()),
423 Err(e) => return Err(e),
424 };
425 let mut attestation_ids_pb: keymaster_attributes::AttestationIds =
426 Message::parse_from_bytes(content.as_slice())
427 .map_err(|e| km_err!(UnknownError, "failed to parse attestation IDs proto: {:?}", e))?;
428
429 let brand = attestation_ids_pb.take_brand();
430 let device = attestation_ids_pb.take_device();
431 let product = attestation_ids_pb.take_product();
432 let serial = attestation_ids_pb.take_serial();
433 let imei = attestation_ids_pb.take_imei();
434 let meid = attestation_ids_pb.take_meid();
435 let manufacturer = attestation_ids_pb.take_manufacturer();
436 let model = attestation_ids_pb.take_model();
437
438 let imei2 = if attestation_ids_pb.has_second_imei() {
439 // A second IMEI has been explicitly provisioned, so use that.
440 attestation_ids_pb.take_second_imei()
441 } else if cfg!(feature = "auto_second_imei") {
442 // No second IMEI has been explicitly provisioned, but dual-SIM devices typically ship with
443 // two sequential IMEIs, so treat (IMEI+1) as the second IMEI.
444 kmr_common::tag::increment_imei(&imei)
445 } else {
446 Vec::new()
447 };
448
449 Ok(AttestationIdInfo { brand, device, product, serial, imei, imei2, meid, manufacturer, model })
450 }
451
452 /// Retrieve that attestation key information for the specified signing algorithm.
453 /// Returns an empty protobuf when file is not found to match c++ behavior
read_attestation_key_content( key_type: SigningAlgorithm, ) -> Result<keymaster_attributes::AttestationKey, Error>454 fn read_attestation_key_content(
455 key_type: SigningAlgorithm,
456 ) -> Result<keymaster_attributes::AttestationKey, Error> {
457 let file_name = get_key_slot_file_name(key_type);
458 let pb = match get_file_contents(&file_name)? {
459 Some(content) => Message::parse_from_bytes(content.as_slice())
460 .map_err(|e| km_err!(UnknownError, "failed to parse attestation key proto: {:?}", e))?,
461 None => keymaster_attributes::AttestationKey::new(),
462 };
463 Ok(pb)
464 }
465
466 /// Retrieve that Uds certificate information
467 /// Returns an empty protobuf when file is not found to match c++ behavior
read_uds_cert_content() -> Result<UdsCerts, Error>468 fn read_uds_cert_content() -> Result<UdsCerts, Error> {
469 let uds_cert_file_pb = match get_file_contents(KM_RKP_UDS_CERT_FILENAME)? {
470 Some(content) => Message::parse_from_bytes(&content)
471 .map_err(|e| km_err!(UnknownError, "failed to parse UdsCerts proto: {:?}", e))?,
472 None => UdsCerts::new(),
473 };
474 Ok(uds_cert_file_pb)
475 }
476
477 /// Retrieve the UdsCerts from the file in secure storage.
read_uds_cert() -> Result<Vec<keymint::Certificate>, Error>478 pub(crate) fn read_uds_cert() -> Result<Vec<keymint::Certificate>, Error> {
479 let mut uds_certs_pb: UdsCerts = read_uds_cert_content()?;
480
481 let certs = uds_certs_pb.take_certs();
482 let num_certs = certs.len();
483 if num_certs == 0 {
484 return Err(km_err!(UnknownError, "UdsCerts file found but it had nothing"));
485 }
486 let mut certificates = vec_try_with_capacity!(num_certs)?;
487 for mut cert in certs {
488 let km_cert_pb = keymint::Certificate { encoded_certificate: cert.take_content() };
489 certificates.push(km_cert_pb);
490 }
491 Ok(certificates)
492 }
493
494 /// Tries to parse an EC private key as a SEC1 private EC key. If that fails, it tries to parse it
495 /// as a PKCS#8 encoded key.
import_ec_key(key_buffer: &[u8]) -> Result<KeyMaterial, Error>496 fn import_ec_key(key_buffer: &[u8]) -> Result<KeyMaterial, Error> {
497 match crypto::ec::import_sec1_private_key(key_buffer) {
498 Ok(key_material) => Ok(key_material),
499 Err(e) => {
500 info!("couldn't parse as sec1 ECPrivateKey, will try as PKCS#8. Error {:?}", e);
501 crypto::ec::import_pkcs8_key(key_buffer)
502 }
503 }
504 }
505
506 /// Tries to parse an RSA key as a PKCS#1 encoded key. If that fails, it tries to parse it as a
507 /// PKCS#8 one.
import_rsa_key(key_buffer: &[u8]) -> Result<KeyMaterial, Error>508 fn import_rsa_key(key_buffer: &[u8]) -> Result<KeyMaterial, Error> {
509 match crypto::rsa::import_pkcs1_key(key_buffer) {
510 Ok((key_material, _, _)) => Ok(key_material),
511 Err(e) => {
512 info!("couldn't parse PKCS#1 RSA key, will try as PKCS#8. Error {:?}", e);
513 let (key_material, _, _) = crypto::rsa::import_pkcs8_key(key_buffer)?;
514 Ok(key_material)
515 }
516 }
517 }
518
519 /// Retrieve the specified attestation key from the file in secure storage.
read_attestation_key(key_type: SigningKeyType) -> Result<KeyMaterial, Error>520 pub(crate) fn read_attestation_key(key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
521 let mut attestation_key_pb: keymaster_attributes::AttestationKey =
522 read_attestation_key_content(key_type.algo_hint)?;
523
524 if !(attestation_key_pb.has_key()) {
525 return Err(km_err!(UnknownError, "attestation Key file found but it had no key"));
526 }
527 let key_buffer = attestation_key_pb.take_key();
528
529 match key_type.algo_hint {
530 SigningAlgorithm::Ec => import_ec_key(&key_buffer),
531 SigningAlgorithm::Rsa => import_rsa_key(&key_buffer),
532 }
533 }
534
get_cert_chain(key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error>535 pub(crate) fn get_cert_chain(key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
536 let mut attestation_certs_pb: keymaster_attributes::AttestationKey =
537 read_attestation_key_content(key_type.algo_hint)?;
538 let certs = attestation_certs_pb.take_certs();
539
540 let num_certs = certs.len();
541 if num_certs == 0 {
542 return Err(km_err!(UnknownError, "attestation Key file found but it had no certs"));
543 }
544 let mut certificates = vec_try_with_capacity!(num_certs)?;
545 for mut cert in certs {
546 let certificate = keymint::Certificate { encoded_certificate: cert.take_content() };
547 certificates.push(certificate);
548 }
549 Ok(certificates)
550 }
551
552 /// Implementation of attestation ID retrieval trait based on protobuf-encoded data in a file in
553 /// secure storage.
554 pub struct AttestationIds;
555
556 impl RetrieveAttestationIds for AttestationIds {
get(&self) -> Result<AttestationIdInfo, Error>557 fn get(&self) -> Result<AttestationIdInfo, Error> {
558 read_attestation_ids()
559 }
560
561 /// Destroy all attestation IDs associated with the device.
destroy_all(&mut self) -> Result<(), Error>562 fn destroy_all(&mut self) -> Result<(), Error> {
563 delete_attestation_ids()
564 }
565 }
566
567 /// Implementation of attestation signing key retrieval trait based on data held in files in secure
568 /// storage.
569 pub struct CertSignInfo;
570
571 impl RetrieveCertSigningInfo for CertSignInfo {
signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error>572 fn signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
573 let result = read_attestation_key(key_type);
574 #[cfg(feature = "soft_attestation_fallback")]
575 if let Err(e) = result {
576 info!("failed to read attestation key ({:?}), fall back to test key", e);
577 let fake = software::CertSignInfo::new();
578 return fake.signing_key(key_type);
579 }
580 result
581 }
582
cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error>583 fn cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
584 let result = get_cert_chain(key_type);
585 #[cfg(feature = "soft_attestation_fallback")]
586 if let Err(e) = result {
587 info!("failed to read attestation chain ({:?}), fall back to test chain", e);
588 let fake = software::CertSignInfo::new();
589 return fake.cert_chain(key_type);
590 }
591 result
592 }
593 }
594
595 #[allow(dead_code)]
596 #[cfg(test)]
597 mod tests {
598 use super::*;
599 use alloc::vec;
600 use core::iter::zip;
601 use kmr_common::wire::AttestationIdInfo;
602 use kmr_ta::device::{SigningAlgorithm, SigningKey, SigningKeyType};
603 use test::{expect, expect_eq};
604
605 // Generated by:
606 // openssl genpkey -out rsakey2.key -outform DER -algorithm RSA -pkeyopt rsa_keygen_bits:2048
607 // openssl pkcs8 -topk8 -in rsakey2.key -outform der -nocrypt -out rsakey.key
608 const RSA_KEY: &'static [u8] = include_bytes!("rsakey.key");
609 // Generated by:
610 // openssl ecparam -name prime256v1 -genkey -outform der -out eckey2.key
611 // openssl pkcs8 -topk8 -in eckey2.key -outform der -nocrypt -out eckey.key
612 const EC_KEY: &'static [u8] = include_bytes!("eckey.key");
613 // Generated by:
614 // openssl genpkey -out rsakey2.key -outform DER -algorithm RSA -pkeyopt rsa_keygen_bits:2048
615 const RSA_KEY_PKCS1: &'static [u8] = include_bytes!("rsakeyrfc3447.key");
616 // Generated by:
617 // openssl ecparam -name prime256v1 -genkey -outform der -out eckey2.key
618 const EC_PRIVATE_KEY_SEC1: &'static [u8] = include_bytes!("eckeysec1.key");
619
delete_key_file(algorithm: SigningAlgorithm)620 fn delete_key_file(algorithm: SigningAlgorithm) {
621 let file_name = get_key_slot_file_name(algorithm);
622 let mut session =
623 Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
624 session.remove(&file_name).expect("Couldn't delete attestation file.");
625 }
626
check_key_file_exists(algorithm: SigningAlgorithm) -> bool627 fn check_key_file_exists(algorithm: SigningAlgorithm) -> bool {
628 let mut session =
629 Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
630 let file_name = get_key_slot_file_name(algorithm);
631 session.open_file(&file_name, OpenMode::Open).is_ok()
632 }
633
check_uds_certs_file_exists() -> bool634 fn check_uds_certs_file_exists() -> bool {
635 let mut session =
636 Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
637 session.open_file(KM_RKP_UDS_CERT_FILENAME, OpenMode::Open).is_ok()
638 }
639
delete_attestation_id_file()640 fn delete_attestation_id_file() {
641 let mut session =
642 Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
643 session.remove(KM_ATTESTATION_ID_FILENAME).expect("Couldn't delete attestation IDs file.");
644 }
645
check_attestation_id_file_exists() -> bool646 fn check_attestation_id_file_exists() -> bool {
647 let mut session =
648 Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
649 session.open_file(KM_ATTESTATION_ID_FILENAME, OpenMode::Open).is_ok()
650 }
651
compare_attestation_ids(lhs: &AttestationIdInfo, rhs: &AttestationIdInfo)652 fn compare_attestation_ids(lhs: &AttestationIdInfo, rhs: &AttestationIdInfo) {
653 expect_eq!(lhs.brand, rhs.brand, "brand doesn't match");
654 expect_eq!(lhs.device, rhs.device, "device doesn't match");
655 expect_eq!(lhs.product, rhs.product, "product doesn't match");
656 expect_eq!(lhs.serial, rhs.serial, "serial doesn't match");
657 expect_eq!(lhs.imei, rhs.imei, "imei doesn't match");
658 expect_eq!(lhs.meid, rhs.meid, "meid doesn't match");
659 expect_eq!(lhs.manufacturer, rhs.manufacturer, "manufacturer doesn't match");
660 expect_eq!(lhs.model, rhs.model, "model doesn't match");
661 expect_eq!(lhs.imei2, rhs.imei2, "imei2 doesn't match");
662 }
663
read_certificates_test(algorithm: SigningAlgorithm)664 fn read_certificates_test(algorithm: SigningAlgorithm) {
665 let mut file =
666 create_attestation_key_file(algorithm).expect("Couldn't create attestation key file");
667 let mut key_cert = keymaster_attributes::AttestationKey::new();
668 let certs_data = [[b'a'; 2048], [b'\0'; 2048], [b'c'; 2048]];
669
670 let mut certs = protobuf::RepeatedField::<keymaster_attributes::AttestationCert>::new();
671
672 for cert_data in certs_data.iter() {
673 let mut cert = keymaster_attributes::AttestationCert::new();
674 cert.set_content(cert_data.to_vec());
675 certs.push(cert);
676 }
677
678 key_cert.set_certs(certs);
679
680 let serialized_buffer = key_cert.write_to_bytes().expect("Couldn't serialize certs");
681
682 file.write_all(&serialized_buffer).unwrap();
683 file.close();
684
685 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
686 let certs = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
687 delete_key_file(algorithm);
688
689 expect_eq!(certs.len(), 3, "Didn't recover all certificates");
690 for (cert, cert_data) in zip(certs.iter(), certs_data.iter()) {
691 expect_eq!(cert.encoded_certificate, cert_data.to_vec(), "Wrong certificate retrieved");
692 }
693
694 // Trying now using just a raw protobuf with same data
695 let field_header = [18, 131, 16, 10, 128, 16];
696 let mut raw_protobuf = Vec::new();
697 for cert_data in certs_data.iter() {
698 raw_protobuf.extend_from_slice(&field_header);
699 raw_protobuf.extend_from_slice(cert_data);
700 }
701
702 let mut file =
703 create_attestation_key_file(algorithm).expect("Couldn't create attestation key file");
704 file.write_all(&raw_protobuf).unwrap();
705 file.close();
706
707 let certs_comp = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
708
709 expect_eq!(certs, certs_comp, "Retrieved certificates didn't match");
710
711 delete_key_file(algorithm);
712 }
713
714 // This test should be run manually as it writes to storage.
715 // #[test]
read_ec_rsa_certificates()716 fn read_ec_rsa_certificates() {
717 read_certificates_test(SigningAlgorithm::Rsa);
718 read_certificates_test(SigningAlgorithm::Ec);
719 }
720
get_test_key_data(algorithm: SigningAlgorithm) -> &'static [u8]721 fn get_test_key_data(algorithm: SigningAlgorithm) -> &'static [u8] {
722 match algorithm {
723 SigningAlgorithm::Rsa => RSA_KEY,
724 SigningAlgorithm::Ec => EC_KEY,
725 }
726 }
727
get_non_pkcs8_test_key_data(algorithm: SigningAlgorithm) -> &'static [u8]728 fn get_non_pkcs8_test_key_data(algorithm: SigningAlgorithm) -> &'static [u8] {
729 match algorithm {
730 SigningAlgorithm::Rsa => RSA_KEY_PKCS1,
731 SigningAlgorithm::Ec => EC_PRIVATE_KEY_SEC1,
732 }
733 }
734
get_test_attestation_key(algorithm: SigningAlgorithm) -> Result<KeyMaterial, Error>735 fn get_test_attestation_key(algorithm: SigningAlgorithm) -> Result<KeyMaterial, Error> {
736 let key_buffer = get_test_key_data(algorithm);
737 let key = match algorithm {
738 SigningAlgorithm::Ec => crypto::ec::import_pkcs8_key(key_buffer)?,
739 SigningAlgorithm::Rsa => {
740 let (key_material, _key_size, _exponent) =
741 crypto::rsa::import_pkcs8_key(key_buffer)?;
742 key_material
743 }
744 };
745 Ok(key)
746 }
747
748 // This test should be run manually as it writes to storage.
749 // #[test]
multiple_attestation_calls_work()750 fn multiple_attestation_calls_work() {
751 let ec_test_key =
752 get_test_attestation_key(SigningAlgorithm::Ec).expect("Couldn't get test key");
753 let rsa_test_key =
754 get_test_attestation_key(SigningAlgorithm::Rsa).expect("Couldn't get test key");
755
756 provision_attestation_key_file(SigningAlgorithm::Ec, EC_KEY)
757 .expect("Couldn't provision key");
758 provision_attestation_key_file(SigningAlgorithm::Rsa, RSA_KEY)
759 .expect("Couldn't provision key");
760 provision_attestation_key_file(SigningAlgorithm::Rsa, &[0])
761 .expect("Couldn't provision key");
762 provision_attestation_key_file(SigningAlgorithm::Ec, &[0, 0])
763 .expect("Couldn't provision key");
764 provision_attestation_key_file(SigningAlgorithm::Ec, EC_KEY)
765 .expect("Couldn't provision key");
766 provision_attestation_key_file(SigningAlgorithm::Rsa, RSA_KEY)
767 .expect("Couldn't provision key");
768
769 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: SigningAlgorithm::Ec };
770 let read_ec_test_key =
771 read_attestation_key(key_type).expect("Couldn't read key from storage");
772
773 let key_type =
774 SigningKeyType { which: SigningKey::Batch, algo_hint: SigningAlgorithm::Rsa };
775 let read_rsa_test_key =
776 read_attestation_key(key_type).expect("Couldn't read key from storage");
777
778 delete_key_file(SigningAlgorithm::Ec);
779 delete_key_file(SigningAlgorithm::Rsa);
780
781 expect_eq!(ec_test_key, read_ec_test_key, "Provisioned key doesn't match original one");
782 expect_eq!(rsa_test_key, read_rsa_test_key, "Provisioned key doesn't match original one");
783 }
784
read_key_test(algorithm: SigningAlgorithm)785 fn read_key_test(algorithm: SigningAlgorithm) {
786 let test_key = get_test_key_data(algorithm);
787
788 provision_attestation_key_file(algorithm, test_key).expect("Couldn't provision key");
789
790 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
791 let att_key = read_attestation_key(key_type).expect("Couldn't read key from storage");
792
793 delete_key_file(algorithm);
794
795 // Trying now using just a raw protobuf with same data
796 let key_header = match algorithm {
797 SigningAlgorithm::Rsa => [10, 191, 9],
798 SigningAlgorithm::Ec => [10, 138, 1],
799 };
800 let mut raw_protobuf = Vec::new();
801 raw_protobuf.extend_from_slice(&key_header);
802 raw_protobuf.extend_from_slice(&test_key);
803
804 let mut file =
805 create_attestation_key_file(algorithm).expect("Couldn't create attestation key file");
806 file.write_all(&raw_protobuf).unwrap();
807 file.close();
808
809 let att_key_comp = read_attestation_key(key_type).expect("Couldn't read key from storage");
810
811 expect_eq!(att_key, att_key_comp);
812
813 delete_key_file(algorithm);
814 }
815
816 // This test should be run manually as it writes to storage.
817 // #[test]
read_ec_rsa_key()818 fn read_ec_rsa_key() {
819 read_key_test(SigningAlgorithm::Rsa);
820 read_key_test(SigningAlgorithm::Ec);
821 }
822
read_non_pkcs8_key_test(algorithm: SigningAlgorithm)823 fn read_non_pkcs8_key_test(algorithm: SigningAlgorithm) {
824 let test_key = get_non_pkcs8_test_key_data(algorithm);
825
826 provision_attestation_key_file(algorithm, test_key).expect("Couldn't provision key");
827
828 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
829 let att_key = read_attestation_key(key_type);
830 expect!(att_key.is_ok(), "Couldn't read a non-pkcs8 key from storage");
831
832 delete_key_file(algorithm);
833 }
834
835 // This test should be run manually as it writes to storage.
836 // #[test]
read_sec1_private_ec_key()837 fn read_sec1_private_ec_key() {
838 read_non_pkcs8_key_test(SigningAlgorithm::Ec);
839 }
840
841 // This test should be run manually as it writes to storage.
842 // #[test]
read_pkcs1_rsa_key()843 fn read_pkcs1_rsa_key() {
844 read_non_pkcs8_key_test(SigningAlgorithm::Rsa);
845 }
846
847 // This test should be run manually as it writes to storage.
848 // #[test]
unprovisioned_keys_certs_reads_produces_error()849 fn unprovisioned_keys_certs_reads_produces_error() {
850 if check_key_file_exists(SigningAlgorithm::Ec) {
851 delete_key_file(SigningAlgorithm::Ec);
852 }
853 if check_key_file_exists(SigningAlgorithm::Rsa) {
854 delete_key_file(SigningAlgorithm::Rsa);
855 }
856 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: SigningAlgorithm::Ec };
857 expect!(read_attestation_key(key_type).is_err(), "Shouldn't be able to read a key");
858 let key_type =
859 SigningKeyType { which: SigningKey::Batch, algo_hint: SigningAlgorithm::Rsa };
860 expect!(read_attestation_key(key_type).is_err(), "Shouldn't be able to read a key");
861 }
862
863 // This test should be run manually as it writes to storage.
864 // #[test]
provision_certs_test()865 fn provision_certs_test() {
866 provision_certs_test_impl(SigningAlgorithm::Ec, true);
867 provision_certs_test_impl(SigningAlgorithm::Rsa, true);
868 provision_certs_test_impl(SigningAlgorithm::Ec, false);
869 provision_certs_test_impl(SigningAlgorithm::Rsa, false);
870 }
871
provision_certs_test_impl(algorithm: SigningAlgorithm, key_first: bool)872 fn provision_certs_test_impl(algorithm: SigningAlgorithm, key_first: bool) {
873 if check_key_file_exists(algorithm) {
874 delete_key_file(algorithm);
875 }
876 let test_key = get_test_key_data(algorithm);
877 if key_first {
878 provision_attestation_key_file(algorithm, test_key).expect("Couldn't provision key");
879 }
880 let cert1 = [b'a'; 2048].as_slice();
881 let cert2 = [b'b'; 2048].as_slice();
882 let cert3 = [b'c'; 2048].as_slice();
883 let certs = [cert1, cert2, cert3];
884 for cert_data in certs.iter() {
885 append_attestation_cert_chain(algorithm, cert_data)
886 .expect("Couldn't provision certificate");
887 }
888 expect!(
889 append_attestation_cert_chain(algorithm, cert3).is_err(),
890 "Shouldn't be able to add more certificates"
891 );
892 if !key_first {
893 provision_attestation_key_file(algorithm, test_key).expect("Couldn't provision key");
894 }
895 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
896 let read_test_key = read_attestation_key(key_type).expect("Couldn't read attestation key");
897 //Getting test key data on a format that can be compared with the key in storage
898 let test_key = get_test_attestation_key(algorithm).expect("Couldn't get test key");
899 expect_eq!(test_key, read_test_key, "Test keys didn't match");
900
901 let read_certs = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
902 expect_eq!(read_certs.len(), 3, "Didn't get all certificates back");
903 for (cert, read_cert) in certs.iter().zip(read_certs.iter()) {
904 expect_eq!(cert, &read_cert.encoded_certificate, "got wrong certificate back");
905 }
906 delete_key_file(algorithm);
907 }
908
clear_certificate_chain_works_when_unprovisioned_impl(algorithm: SigningAlgorithm)909 fn clear_certificate_chain_works_when_unprovisioned_impl(algorithm: SigningAlgorithm) {
910 if check_key_file_exists(algorithm) {
911 delete_key_file(algorithm);
912 }
913 clear_attestation_cert_chain(algorithm).expect("couldn't clear certificate chain");
914 expect!(
915 check_key_file_exists(algorithm) == false,
916 "Shouldn't have created a file if it didn't existed originally"
917 );
918 }
919
920 // This test should be run manually as it writes to storage.
921 // #[test]
clear_certificate_chain_works_when_unprovisioned()922 fn clear_certificate_chain_works_when_unprovisioned() {
923 clear_certificate_chain_works_when_unprovisioned_impl(SigningAlgorithm::Ec);
924 clear_certificate_chain_works_when_unprovisioned_impl(SigningAlgorithm::Rsa);
925 }
926
clear_certificate_chain_works_impl(algorithm: SigningAlgorithm)927 fn clear_certificate_chain_works_impl(algorithm: SigningAlgorithm) {
928 if check_key_file_exists(algorithm) {
929 delete_key_file(algorithm);
930 }
931 let test_key = get_test_key_data(algorithm);
932 provision_attestation_key_file(algorithm, test_key).expect("Couldn't provision key");
933 let cert = [b'a'; 2048].as_slice();
934 append_attestation_cert_chain(algorithm, cert).expect("Couldn't provision certificate");
935
936 let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
937 let read_certs = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
938 expect_eq!(read_certs.len(), 1, "Didn't get all certificates back");
939
940 clear_attestation_cert_chain(algorithm).expect("couldn't clear certificate chain");
941
942 expect!(get_cert_chain(key_type).is_err(), "Certificates were not deleted");
943
944 let read_test_key = read_attestation_key(key_type).expect("Couldn't read attestation key");
945 //Getting test key data on a format that can be compared with the key in storage
946 let test_key = get_test_attestation_key(algorithm).expect("Couldn't get test key");
947 expect_eq!(test_key, read_test_key, "Test keys didn't match");
948
949 delete_key_file(algorithm);
950 }
951
952 // This test should be run manually as it writes to storage.
953 // #[test]
clear_certificate_chain_works()954 fn clear_certificate_chain_works() {
955 clear_certificate_chain_works_impl(SigningAlgorithm::Ec);
956 clear_certificate_chain_works_impl(SigningAlgorithm::Rsa);
957 }
958
959 // This test should be run manually as it writes to storage.
960 // #[test]
provision_uds_certs_works()961 fn provision_uds_certs_works() {
962 if check_uds_certs_file_exists() {
963 delete_uds_cert_file().expect("Couldn't delete UdsCerts file");
964 }
965 let cert1 = [b'a'; 500].as_slice();
966 let cert2 = [b'b'; 500].as_slice();
967 let cert3 = [b'c'; 500].as_slice();
968 let certs = [cert1, cert2, cert3];
969 for cert_data in certs.iter() {
970 append_uds_cert_chain(cert_data).expect("Couldn't provision UdsCerts");
971 }
972 expect!(
973 append_uds_cert_chain(cert3).is_err(),
974 "Shouldn't be able to add more certificates"
975 );
976
977 let read_uds_certs = read_uds_cert().expect("Couldn't read attestation key");
978 for i in 0..certs.len() {
979 expect_eq!(certs[i], read_uds_certs[i].encoded_certificate, "Uds Certs didn't match");
980 }
981
982 delete_uds_cert_file().expect("Couldn't delete UdsCerts file");
983 }
984
985 // This test should be run manually as it writes to storage.
986 // #[test]
clear_uds_certs_works()987 fn clear_uds_certs_works() {
988 if check_uds_certs_file_exists() {
989 delete_uds_cert_file().expect("Couldn't delete UdsCerts file");
990 }
991 let cert = [b'a'; 500].as_slice();
992 append_uds_cert_chain(cert).expect("Couldn't provision certificate");
993 let read_certs = read_uds_cert().expect("Couldn't get UdsCerts from storage");
994 expect_eq!(read_certs.len(), 1, "Didn't get all certificates back");
995
996 maybe_delete_uds_cert_chain().expect("Couldn't delete UdsCerts file");
997
998 expect!(read_uds_cert().is_err(), "Certificates were not deleted");
999 }
1000
1001 // This test should be run manually as it writes to storage.
1002 // #[test]
get_clear_uds_certs_after_delete_works()1003 fn get_clear_uds_certs_after_delete_works() {
1004 if check_uds_certs_file_exists() {
1005 delete_uds_cert_file().expect("Couldn't delete UdsCerts file");
1006 }
1007 let cert = [b'a'; 500].as_slice();
1008 append_uds_cert_chain(cert).expect("Couldn't provision certificate");
1009 let read_certs = read_uds_cert().expect("Couldn't get UdsCerts from storage");
1010 expect_eq!(read_certs.len(), 1, "Didn't get all certificates back");
1011
1012 maybe_delete_uds_cert_chain().expect("couldn't delete UdsCerts file");
1013
1014 let expected_clear_uds_cert =
1015 read_uds_cert_content().expect("Couldn't get a default UdsCerts objec");
1016 expect_eq!(expected_clear_uds_cert.certs.len(), 0, "Not a clear UdsCerts object");
1017 }
1018
1019 // This test should be run manually as it writes to storage.
1020 // #[test]
unprovisioned_attestation_ids_do_not_error()1021 fn unprovisioned_attestation_ids_do_not_error() {
1022 if check_attestation_id_file_exists() {
1023 delete_attestation_id_file();
1024 }
1025 let attestation_ids =
1026 read_attestation_ids().expect("Couldn't read attestation IDs when unprovisioned");
1027
1028 expect_eq!(attestation_ids.brand.len(), 0, "brand should be empty");
1029 expect_eq!(attestation_ids.device.len(), 0, "device should be empty");
1030 expect_eq!(attestation_ids.product.len(), 0, "product should be empty");
1031 expect_eq!(attestation_ids.serial.len(), 0, "serial should be empty");
1032 expect_eq!(attestation_ids.imei.len(), 0, "imei should be empty");
1033 expect_eq!(attestation_ids.meid.len(), 0, "meid should be empty");
1034 expect_eq!(attestation_ids.manufacturer.len(), 0, "manufacturer should be empty");
1035 expect_eq!(attestation_ids.model.len(), 0, "model should be empty");
1036 expect_eq!(attestation_ids.imei2.len(), 0, "imei2 should be empty");
1037 }
1038
1039 // This test should be run manually as it writes to storage.
1040 // #[test]
single_attestation_id_field()1041 fn single_attestation_id_field() {
1042 let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
1043
1044 let mut attestation_ids = keymaster_attributes::AttestationIds::new();
1045 let brand = b"new brand";
1046
1047 attestation_ids.set_brand(brand.to_vec());
1048
1049 let serialized_buffer =
1050 attestation_ids.write_to_bytes().expect("Couldn't serialize attestationIds");
1051
1052 file.write_all(&serialized_buffer).unwrap();
1053 file.close();
1054
1055 let attestation_ids_info =
1056 read_attestation_ids().expect("Couldn't read attestation IDs from storage");
1057
1058 delete_attestation_id_file();
1059 expect_eq!(
1060 check_attestation_id_file_exists(),
1061 false,
1062 "Couldn't delete attestation IDs file"
1063 );
1064
1065 expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
1066 expect_eq!(attestation_ids_info.device.len(), 0, "shouldn't have a device");
1067 expect_eq!(attestation_ids_info.product.len(), 0, "shouldn't have a product");
1068 expect_eq!(attestation_ids_info.serial.len(), 0, "shouldn't have a serial");
1069 expect_eq!(attestation_ids_info.imei.len(), 0, "shouldn't have a imei");
1070 expect_eq!(attestation_ids_info.meid.len(), 0, "shouldn't have a meid");
1071 expect_eq!(attestation_ids_info.manufacturer.len(), 0, "shouldn't have a manufacturer");
1072 expect_eq!(attestation_ids_info.model.len(), 0, "shouldn't have a model");
1073 expect_eq!(attestation_ids_info.imei2.len(), 0, "shouldn't have a model");
1074
1075 // Now using a raw protobuf
1076 let raw_protobuf = [10, 9, 110, 101, 119, 32, 98, 114, 97, 110, 100];
1077
1078 let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
1079 file.write_all(&raw_protobuf).unwrap();
1080 file.close();
1081
1082 let attestation_ids_comp = read_attestation_ids()
1083 .expect("Couldn't read comparison set of attestation IDs from storage");
1084
1085 compare_attestation_ids(&attestation_ids_info, &attestation_ids_comp);
1086
1087 delete_attestation_id_file();
1088 expect_eq!(
1089 check_attestation_id_file_exists(),
1090 false,
1091 "Couldn't delete attestation IDs file"
1092 );
1093 }
1094
1095 // This test should be run manually as it writes to storage.
1096 // #[test]
test_provision_attestation_id_file()1097 fn test_provision_attestation_id_file() {
1098 let brand = b"unknown brand";
1099 let product = b"";
1100 let device = b"my brand new device";
1101 let serial = vec![b'9'; 64];
1102 let imei = b" ";
1103 let meid = b"\0";
1104 let manufacturer = b"manufacturer #$%%^";
1105 let model = b"working one";
1106 let imei2 = b"0";
1107
1108 assert!(provision_attestation_id_file(
1109 brand,
1110 product,
1111 device,
1112 &serial,
1113 imei,
1114 meid,
1115 manufacturer,
1116 model,
1117 Some(imei2)
1118 )
1119 .is_ok());
1120
1121 let attestation_ids_info =
1122 read_attestation_ids().expect("Couldn't read attestation IDs from storage");
1123
1124 delete_attestation_id_file();
1125 expect_eq!(
1126 check_attestation_id_file_exists(),
1127 false,
1128 "Couldn't delete attestation IDs file"
1129 );
1130
1131 expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
1132 expect_eq!(attestation_ids_info.device, device.to_vec(), "device doesn't match");
1133 expect_eq!(attestation_ids_info.product, product.to_vec(), "product doesn't match");
1134 expect_eq!(attestation_ids_info.serial, serial, "serial doesn't match");
1135 expect_eq!(attestation_ids_info.imei, imei.to_vec(), "imei doesn't match");
1136 expect_eq!(attestation_ids_info.meid, meid.to_vec(), "meid doesn't match");
1137 expect_eq!(
1138 attestation_ids_info.manufacturer,
1139 manufacturer.to_vec(),
1140 "manufacturer doesn't match"
1141 );
1142 expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
1143 expect_eq!(attestation_ids_info.imei2, imei2.to_vec(), "imei2 doesn't match");
1144 }
1145
1146 #[test]
test_provision_attestation_id_file_imei2_none()1147 fn test_provision_attestation_id_file_imei2_none() {
1148 let brand = b"unknown brand";
1149 let product = b"";
1150 let device = b"my brand new device";
1151 let serial = vec![b'9'; 64];
1152 let imei = b"000000123456782";
1153 let meid = b"\0";
1154 let manufacturer = b"manufacturer #$%%^";
1155 let model = b"working one";
1156 let expected_imei2 = b"123456790";
1157
1158 assert!(provision_attestation_id_file(
1159 brand,
1160 product,
1161 device,
1162 &serial,
1163 imei,
1164 meid,
1165 manufacturer,
1166 model,
1167 None
1168 )
1169 .is_ok());
1170
1171 let attestation_ids_info =
1172 read_attestation_ids().expect("Couldn't read attestation IDs from storage");
1173
1174 delete_attestation_id_file();
1175 expect_eq!(
1176 check_attestation_id_file_exists(),
1177 false,
1178 "Couldn't delete attestation IDs file"
1179 );
1180
1181 expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
1182 expect_eq!(attestation_ids_info.device, device.to_vec(), "device doesn't match");
1183 expect_eq!(attestation_ids_info.product, product.to_vec(), "product doesn't match");
1184 expect_eq!(attestation_ids_info.serial, serial, "serial doesn't match");
1185 expect_eq!(attestation_ids_info.imei, imei.to_vec(), "imei doesn't match");
1186 expect_eq!(attestation_ids_info.meid, meid.to_vec(), "meid doesn't match");
1187 expect_eq!(
1188 attestation_ids_info.manufacturer,
1189 manufacturer.to_vec(),
1190 "manufacturer doesn't match"
1191 );
1192 expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
1193 expect_eq!(attestation_ids_info.imei2, expected_imei2.to_vec(), "imei2 doesn't match");
1194 }
1195
1196 // This test should be run manually as it writes to storage.
1197 // #[test]
all_attestation_id_fields()1198 fn all_attestation_id_fields() {
1199 let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
1200 let mut attestation_ids = keymaster_attributes::AttestationIds::new();
1201 let brand = b"unknown brand";
1202 let device = b"my brand new device";
1203 let product = b"";
1204 let serial = vec![b'9'; 64];
1205 let imei = b" ";
1206 let meid = b"\0";
1207 let manufacturer = b"manufacturer #$%%^";
1208 let model = b"working one";
1209 let imei2 = b"0";
1210
1211 attestation_ids.set_brand(brand.to_vec());
1212 attestation_ids.set_device(device.to_vec());
1213 attestation_ids.set_product(product.to_vec());
1214 attestation_ids.set_serial(serial.clone());
1215 attestation_ids.set_imei(imei.to_vec());
1216 attestation_ids.set_meid(meid.to_vec());
1217 attestation_ids.set_manufacturer(manufacturer.to_vec());
1218 attestation_ids.set_model(model.to_vec());
1219 attestation_ids.set_second_imei(imei2.to_vec());
1220
1221 let serialized_buffer =
1222 attestation_ids.write_to_bytes().expect("Couldn't serialize attestationIds");
1223
1224 file.write_all(&serialized_buffer).unwrap();
1225 file.close();
1226
1227 let attestation_ids_info =
1228 read_attestation_ids().expect("Couldn't read attestation IDs from storage");
1229
1230 delete_attestation_id_file();
1231 expect_eq!(
1232 check_attestation_id_file_exists(),
1233 false,
1234 "Couldn't delete attestation IDs file"
1235 );
1236
1237 expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
1238 expect_eq!(attestation_ids_info.device, device.to_vec(), "device doesn't match");
1239 expect_eq!(attestation_ids_info.product, product.to_vec(), "product doesn't match");
1240 expect_eq!(attestation_ids_info.serial, serial, "serial doesn't match");
1241 expect_eq!(attestation_ids_info.imei, imei.to_vec(), "imei doesn't match");
1242 expect_eq!(attestation_ids_info.meid, meid.to_vec(), "meid doesn't match");
1243 expect_eq!(
1244 attestation_ids_info.manufacturer,
1245 manufacturer.to_vec(),
1246 "manufacturer doesn't match"
1247 );
1248 expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
1249 expect_eq!(attestation_ids_info.imei2, imei2.to_vec(), "imei2 doesn't match");
1250
1251 // Now trying the same from a raw protobuf
1252 let raw_protobuf = [
1253 10, 13, 117, 110, 107, 110, 111, 119, 110, 32, 98, 114, 97, 110, 100, 18, 19, 109, 121,
1254 32, 98, 114, 97, 110, 100, 32, 110, 101, 119, 32, 100, 101, 118, 105, 99, 101, 26, 0,
1255 34, 64, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
1256 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
1257 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
1258 42, 1, 32, 50, 1, 0, 58, 18, 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114,
1259 32, 35, 36, 37, 37, 94, 66, 11, 119, 111, 114, 107, 105, 110, 103, 32, 111, 110, 101,
1260 74, 1, 48,
1261 ];
1262
1263 let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
1264 file.write_all(&raw_protobuf).unwrap();
1265 file.close();
1266
1267 let attestation_ids_comp = read_attestation_ids()
1268 .expect("Couldn't read comparison set of attestation IDs from storage");
1269
1270 compare_attestation_ids(&attestation_ids_info, &attestation_ids_comp);
1271
1272 delete_attestation_id_file();
1273 expect_eq!(
1274 check_attestation_id_file_exists(),
1275 false,
1276 "Couldn't delete attestation IDs file"
1277 );
1278 }
1279
1280 // This test should be run manually as it writes to storage.
1281 // #[test]
delete_attestation_ids_file()1282 fn delete_attestation_ids_file() {
1283 let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
1284 let raw_protobuf = [10, 9, 110, 101, 119, 32, 98, 114, 97, 110, 100];
1285 file.write_all(&raw_protobuf).unwrap();
1286 file.close();
1287
1288 expect!(check_attestation_id_file_exists(), "Couldn't create attestation IDs file");
1289 expect!(delete_attestation_ids().is_ok(), "Couldn't delete attestation IDs file");
1290 expect_eq!(
1291 check_attestation_id_file_exists(),
1292 false,
1293 "Attestation IDs file was not deleted"
1294 );
1295 }
1296
1297 #[test]
protobuf_lib_version()1298 fn protobuf_lib_version() {
1299 // We are generating the protobuf rust files out of tree because we cannot do it in-tree yet
1300 // Because the version of the tool used to autogenerate the files has to match the protobuf
1301 // library version, we check it here.
1302 expect_eq!("2.27.1", protobuf::VERSION, "autogenerated files version mistmatch");
1303 }
1304 }
1305