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