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