xref: /aosp_15_r20/system/keymint/ta/src/cert.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! Generation of certificates and attestation extensions.
16*9860b763SAndroid Build Coastguard Worker 
17*9860b763SAndroid Build Coastguard Worker use crate::keys::SigningInfo;
18*9860b763SAndroid Build Coastguard Worker use alloc::{borrow::Cow, vec::Vec};
19*9860b763SAndroid Build Coastguard Worker use core::time::Duration;
20*9860b763SAndroid Build Coastguard Worker use der::asn1::{BitString, OctetString, OctetStringRef, SetOfVec};
21*9860b763SAndroid Build Coastguard Worker use der::{
22*9860b763SAndroid Build Coastguard Worker     asn1::{GeneralizedTime, Null, UtcTime},
23*9860b763SAndroid Build Coastguard Worker     oid::AssociatedOid,
24*9860b763SAndroid Build Coastguard Worker     Enumerated, Sequence,
25*9860b763SAndroid Build Coastguard Worker };
26*9860b763SAndroid Build Coastguard Worker use der::{Decode, Encode, EncodeValue, ErrorKind, Length};
27*9860b763SAndroid Build Coastguard Worker use flagset::FlagSet;
28*9860b763SAndroid Build Coastguard Worker use kmr_common::crypto::KeyMaterial;
29*9860b763SAndroid Build Coastguard Worker use kmr_common::{
30*9860b763SAndroid Build Coastguard Worker     crypto, der_err, get_tag_value, km_err, tag, try_to_vec, vec_try_with_capacity, Error,
31*9860b763SAndroid Build Coastguard Worker };
32*9860b763SAndroid Build Coastguard Worker use kmr_common::{get_bool_tag_value, get_opt_tag_value, FallibleAllocExt};
33*9860b763SAndroid Build Coastguard Worker use kmr_wire::{
34*9860b763SAndroid Build Coastguard Worker     keymint,
35*9860b763SAndroid Build Coastguard Worker     keymint::{
36*9860b763SAndroid Build Coastguard Worker         from_raw_tag_value, raw_tag_value, DateTime, ErrorCode, KeyCharacteristics, KeyParam,
37*9860b763SAndroid Build Coastguard Worker         KeyPurpose, Tag,
38*9860b763SAndroid Build Coastguard Worker     },
39*9860b763SAndroid Build Coastguard Worker     KeySizeInBits, RsaExponent,
40*9860b763SAndroid Build Coastguard Worker };
41*9860b763SAndroid Build Coastguard Worker use spki::{AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfoOwned};
42*9860b763SAndroid Build Coastguard Worker use x509_cert::serial_number::SerialNumber;
43*9860b763SAndroid Build Coastguard Worker use x509_cert::{
44*9860b763SAndroid Build Coastguard Worker     certificate::{Certificate, TbsCertificate, Version},
45*9860b763SAndroid Build Coastguard Worker     ext::pkix::{constraints::BasicConstraints, KeyUsage, KeyUsages},
46*9860b763SAndroid Build Coastguard Worker     ext::Extension,
47*9860b763SAndroid Build Coastguard Worker     name::RdnSequence,
48*9860b763SAndroid Build Coastguard Worker     time::Time,
49*9860b763SAndroid Build Coastguard Worker };
50*9860b763SAndroid Build Coastguard Worker 
51*9860b763SAndroid Build Coastguard Worker /// OID value for the Android Attestation extension.
52*9860b763SAndroid Build Coastguard Worker pub const ATTESTATION_EXTENSION_OID: ObjectIdentifier =
53*9860b763SAndroid Build Coastguard Worker     ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.1.17");
54*9860b763SAndroid Build Coastguard Worker 
55*9860b763SAndroid Build Coastguard Worker /// Empty value to use in the `RootOfTrust.verifiedBootKey` field in attestations
56*9860b763SAndroid Build Coastguard Worker /// if an empty value was passed to the bootloader.
57*9860b763SAndroid Build Coastguard Worker const EMPTY_BOOT_KEY: [u8; 32] = [0u8; 32];
58*9860b763SAndroid Build Coastguard Worker 
59*9860b763SAndroid Build Coastguard Worker /// Build an ASN.1 DER-encodable `Certificate`.
certificate(tbs_cert: TbsCertificate, sig_val: &[u8]) -> Result<Certificate, Error>60*9860b763SAndroid Build Coastguard Worker pub(crate) fn certificate(tbs_cert: TbsCertificate, sig_val: &[u8]) -> Result<Certificate, Error> {
61*9860b763SAndroid Build Coastguard Worker     Ok(Certificate {
62*9860b763SAndroid Build Coastguard Worker         signature_algorithm: tbs_cert.signature.clone(),
63*9860b763SAndroid Build Coastguard Worker         tbs_certificate: tbs_cert,
64*9860b763SAndroid Build Coastguard Worker         signature: BitString::new(0, sig_val)
65*9860b763SAndroid Build Coastguard Worker             .map_err(|e| der_err!(e, "failed to build BitString"))?,
66*9860b763SAndroid Build Coastguard Worker     })
67*9860b763SAndroid Build Coastguard Worker }
68*9860b763SAndroid Build Coastguard Worker 
69*9860b763SAndroid Build Coastguard Worker /// Build an ASN.1 DER-encodable `tbsCertificate`.
tbs_certificate<'a>( info: &'a Option<SigningInfo>, spki: SubjectPublicKeyInfoOwned, key_usage_ext_bits: &'a [u8], basic_constraint_ext_val: Option<&'a [u8]>, attestation_ext: Option<&'a [u8]>, chars: &'a [KeyParam], params: &'a [KeyParam], ) -> Result<TbsCertificate, Error>70*9860b763SAndroid Build Coastguard Worker pub(crate) fn tbs_certificate<'a>(
71*9860b763SAndroid Build Coastguard Worker     info: &'a Option<SigningInfo>,
72*9860b763SAndroid Build Coastguard Worker     spki: SubjectPublicKeyInfoOwned,
73*9860b763SAndroid Build Coastguard Worker     key_usage_ext_bits: &'a [u8],
74*9860b763SAndroid Build Coastguard Worker     basic_constraint_ext_val: Option<&'a [u8]>,
75*9860b763SAndroid Build Coastguard Worker     attestation_ext: Option<&'a [u8]>,
76*9860b763SAndroid Build Coastguard Worker     chars: &'a [KeyParam],
77*9860b763SAndroid Build Coastguard Worker     params: &'a [KeyParam],
78*9860b763SAndroid Build Coastguard Worker ) -> Result<TbsCertificate, Error> {
79*9860b763SAndroid Build Coastguard Worker     let cert_serial = tag::get_cert_serial(params)?;
80*9860b763SAndroid Build Coastguard Worker     let cert_subject = tag::get_cert_subject(params)?;
81*9860b763SAndroid Build Coastguard Worker     let not_before = get_tag_value!(params, CertificateNotBefore, ErrorCode::MissingNotBefore)?;
82*9860b763SAndroid Build Coastguard Worker     let not_after = get_tag_value!(params, CertificateNotAfter, ErrorCode::MissingNotAfter)?;
83*9860b763SAndroid Build Coastguard Worker 
84*9860b763SAndroid Build Coastguard Worker     // Determine the OID part of the `AlgorithmIdentifier`; we do not support any signing key
85*9860b763SAndroid Build Coastguard Worker     // types that have parameters in the `AlgorithmIdentifier`
86*9860b763SAndroid Build Coastguard Worker     let sig_alg_oid = match info {
87*9860b763SAndroid Build Coastguard Worker         Some(info) => match info.signing_key {
88*9860b763SAndroid Build Coastguard Worker             KeyMaterial::Rsa(_) => crypto::rsa::SHA256_PKCS1_SIGNATURE_OID,
89*9860b763SAndroid Build Coastguard Worker             KeyMaterial::Ec(curve, _, _) => crypto::ec::curve_to_signing_oid(curve),
90*9860b763SAndroid Build Coastguard Worker             _ => {
91*9860b763SAndroid Build Coastguard Worker                 return Err(km_err!(UnsupportedAlgorithm, "unexpected cert signing key type"));
92*9860b763SAndroid Build Coastguard Worker             }
93*9860b763SAndroid Build Coastguard Worker         },
94*9860b763SAndroid Build Coastguard Worker         None => {
95*9860b763SAndroid Build Coastguard Worker             // No signing key, so signature will be empty, but we still need a value here.
96*9860b763SAndroid Build Coastguard Worker             match tag::get_algorithm(params)? {
97*9860b763SAndroid Build Coastguard Worker                 keymint::Algorithm::Rsa => crypto::rsa::SHA256_PKCS1_SIGNATURE_OID,
98*9860b763SAndroid Build Coastguard Worker                 keymint::Algorithm::Ec => {
99*9860b763SAndroid Build Coastguard Worker                     crypto::ec::curve_to_signing_oid(tag::get_ec_curve(chars)?)
100*9860b763SAndroid Build Coastguard Worker                 }
101*9860b763SAndroid Build Coastguard Worker                 alg => {
102*9860b763SAndroid Build Coastguard Worker                     return Err(km_err!(
103*9860b763SAndroid Build Coastguard Worker                         UnsupportedAlgorithm,
104*9860b763SAndroid Build Coastguard Worker                         "unexpected algorithm for public key {:?}",
105*9860b763SAndroid Build Coastguard Worker                         alg
106*9860b763SAndroid Build Coastguard Worker                     ))
107*9860b763SAndroid Build Coastguard Worker                 }
108*9860b763SAndroid Build Coastguard Worker             }
109*9860b763SAndroid Build Coastguard Worker         }
110*9860b763SAndroid Build Coastguard Worker     };
111*9860b763SAndroid Build Coastguard Worker     let cert_issuer = match &info {
112*9860b763SAndroid Build Coastguard Worker         Some(info) => &info.issuer_subject,
113*9860b763SAndroid Build Coastguard Worker         None => cert_subject,
114*9860b763SAndroid Build Coastguard Worker     };
115*9860b763SAndroid Build Coastguard Worker 
116*9860b763SAndroid Build Coastguard Worker     // Build certificate extensions
117*9860b763SAndroid Build Coastguard Worker     let key_usage_extension = Extension {
118*9860b763SAndroid Build Coastguard Worker         extn_id: KeyUsage::OID,
119*9860b763SAndroid Build Coastguard Worker         critical: true,
120*9860b763SAndroid Build Coastguard Worker         extn_value: OctetString::new(key_usage_ext_bits)
121*9860b763SAndroid Build Coastguard Worker             .map_err(|e| der_err!(e, "failed to build OctetString"))?,
122*9860b763SAndroid Build Coastguard Worker     };
123*9860b763SAndroid Build Coastguard Worker 
124*9860b763SAndroid Build Coastguard Worker     let mut cert_extensions = vec_try_with_capacity!(3)?;
125*9860b763SAndroid Build Coastguard Worker     cert_extensions.push(key_usage_extension); // capacity enough
126*9860b763SAndroid Build Coastguard Worker 
127*9860b763SAndroid Build Coastguard Worker     if let Some(basic_constraint_ext_val) = basic_constraint_ext_val {
128*9860b763SAndroid Build Coastguard Worker         let basic_constraint_ext = Extension {
129*9860b763SAndroid Build Coastguard Worker             extn_id: BasicConstraints::OID,
130*9860b763SAndroid Build Coastguard Worker             critical: true,
131*9860b763SAndroid Build Coastguard Worker             extn_value: OctetString::new(basic_constraint_ext_val)
132*9860b763SAndroid Build Coastguard Worker                 .map_err(|e| der_err!(e, "failed to build OctetString"))?,
133*9860b763SAndroid Build Coastguard Worker         };
134*9860b763SAndroid Build Coastguard Worker         cert_extensions.push(basic_constraint_ext); // capacity enough
135*9860b763SAndroid Build Coastguard Worker     }
136*9860b763SAndroid Build Coastguard Worker 
137*9860b763SAndroid Build Coastguard Worker     if let Some(attest_extn_val) = attestation_ext {
138*9860b763SAndroid Build Coastguard Worker         let attest_ext = Extension {
139*9860b763SAndroid Build Coastguard Worker             extn_id: AttestationExtension::OID,
140*9860b763SAndroid Build Coastguard Worker             critical: false,
141*9860b763SAndroid Build Coastguard Worker             extn_value: OctetString::new(attest_extn_val)
142*9860b763SAndroid Build Coastguard Worker                 .map_err(|e| der_err!(e, "failed to build OctetString"))?,
143*9860b763SAndroid Build Coastguard Worker         };
144*9860b763SAndroid Build Coastguard Worker         cert_extensions.push(attest_ext) // capacity enough
145*9860b763SAndroid Build Coastguard Worker     }
146*9860b763SAndroid Build Coastguard Worker 
147*9860b763SAndroid Build Coastguard Worker     Ok(TbsCertificate {
148*9860b763SAndroid Build Coastguard Worker         version: Version::V3,
149*9860b763SAndroid Build Coastguard Worker         serial_number: SerialNumber::new(cert_serial)
150*9860b763SAndroid Build Coastguard Worker             .map_err(|e| der_err!(e, "failed to build serial number for {:?}", cert_serial))?,
151*9860b763SAndroid Build Coastguard Worker         signature: AlgorithmIdentifier { oid: sig_alg_oid, parameters: None },
152*9860b763SAndroid Build Coastguard Worker         issuer: RdnSequence::from_der(cert_issuer)
153*9860b763SAndroid Build Coastguard Worker             .map_err(|e| der_err!(e, "failed to build issuer"))?,
154*9860b763SAndroid Build Coastguard Worker         validity: x509_cert::time::Validity {
155*9860b763SAndroid Build Coastguard Worker             not_before: validity_time_from_datetime(not_before)?,
156*9860b763SAndroid Build Coastguard Worker             not_after: validity_time_from_datetime(not_after)?,
157*9860b763SAndroid Build Coastguard Worker         },
158*9860b763SAndroid Build Coastguard Worker         subject: RdnSequence::from_der(cert_subject)
159*9860b763SAndroid Build Coastguard Worker             .map_err(|e| der_err!(e, "failed to build subject"))?,
160*9860b763SAndroid Build Coastguard Worker         subject_public_key_info: spki,
161*9860b763SAndroid Build Coastguard Worker         issuer_unique_id: None,
162*9860b763SAndroid Build Coastguard Worker         subject_unique_id: None,
163*9860b763SAndroid Build Coastguard Worker         extensions: Some(cert_extensions),
164*9860b763SAndroid Build Coastguard Worker     })
165*9860b763SAndroid Build Coastguard Worker }
166*9860b763SAndroid Build Coastguard Worker 
167*9860b763SAndroid Build Coastguard Worker /// Extract the Subject field from a `keymint::Certificate` as DER-encoded data.
extract_subject(cert: &keymint::Certificate) -> Result<Vec<u8>, Error>168*9860b763SAndroid Build Coastguard Worker pub(crate) fn extract_subject(cert: &keymint::Certificate) -> Result<Vec<u8>, Error> {
169*9860b763SAndroid Build Coastguard Worker     let cert = x509_cert::Certificate::from_der(&cert.encoded_certificate)
170*9860b763SAndroid Build Coastguard Worker         .map_err(|e| km_err!(EncodingError, "failed to parse certificate: {:?}", e))?;
171*9860b763SAndroid Build Coastguard Worker     let subject_data = cert
172*9860b763SAndroid Build Coastguard Worker         .tbs_certificate
173*9860b763SAndroid Build Coastguard Worker         .subject
174*9860b763SAndroid Build Coastguard Worker         .to_der()
175*9860b763SAndroid Build Coastguard Worker         .map_err(|e| km_err!(EncodingError, "failed to DER-encode subject: {:?}", e))?;
176*9860b763SAndroid Build Coastguard Worker     Ok(subject_data)
177*9860b763SAndroid Build Coastguard Worker }
178*9860b763SAndroid Build Coastguard Worker 
179*9860b763SAndroid Build Coastguard Worker /// Construct x.509-cert::time::Time from `DateTime`.
180*9860b763SAndroid Build Coastguard Worker /// RFC 5280 section 4.1.2.5 requires that UtcTime is used up to 2049
181*9860b763SAndroid Build Coastguard Worker /// and GeneralizedTime from 2050 onwards
validity_time_from_datetime(when: DateTime) -> Result<Time, Error>182*9860b763SAndroid Build Coastguard Worker fn validity_time_from_datetime(when: DateTime) -> Result<Time, Error> {
183*9860b763SAndroid Build Coastguard Worker     let dt_err = |_| Error::Der(ErrorKind::DateTime);
184*9860b763SAndroid Build Coastguard Worker     let secs_since_epoch: i64 = when.ms_since_epoch / 1000;
185*9860b763SAndroid Build Coastguard Worker 
186*9860b763SAndroid Build Coastguard Worker     if when.ms_since_epoch >= 0 {
187*9860b763SAndroid Build Coastguard Worker         const MAX_UTC_TIME: Duration = Duration::from_secs(2524608000); // 2050-01-01T00:00:00Z
188*9860b763SAndroid Build Coastguard Worker 
189*9860b763SAndroid Build Coastguard Worker         let duration = Duration::from_secs(u64::try_from(secs_since_epoch).map_err(dt_err)?);
190*9860b763SAndroid Build Coastguard Worker         if duration >= MAX_UTC_TIME {
191*9860b763SAndroid Build Coastguard Worker             Ok(Time::GeneralTime(
192*9860b763SAndroid Build Coastguard Worker                 GeneralizedTime::from_unix_duration(duration)
193*9860b763SAndroid Build Coastguard Worker                     .map_err(|e| der_err!(e, "failed to build GeneralTime for {:?}", when))?,
194*9860b763SAndroid Build Coastguard Worker             ))
195*9860b763SAndroid Build Coastguard Worker         } else {
196*9860b763SAndroid Build Coastguard Worker             Ok(Time::UtcTime(
197*9860b763SAndroid Build Coastguard Worker                 UtcTime::from_unix_duration(duration)
198*9860b763SAndroid Build Coastguard Worker                     .map_err(|e| der_err!(e, "failed to build UtcTime for {:?}", when))?,
199*9860b763SAndroid Build Coastguard Worker             ))
200*9860b763SAndroid Build Coastguard Worker         }
201*9860b763SAndroid Build Coastguard Worker     } else {
202*9860b763SAndroid Build Coastguard Worker         // TODO: cope with negative offsets from Unix Epoch.
203*9860b763SAndroid Build Coastguard Worker         Ok(Time::GeneralTime(
204*9860b763SAndroid Build Coastguard Worker             GeneralizedTime::from_unix_duration(Duration::from_secs(0))
205*9860b763SAndroid Build Coastguard Worker                 .map_err(|e| der_err!(e, "failed to build GeneralizedTime(0) for {:?}", when))?,
206*9860b763SAndroid Build Coastguard Worker         ))
207*9860b763SAndroid Build Coastguard Worker     }
208*9860b763SAndroid Build Coastguard Worker }
209*9860b763SAndroid Build Coastguard Worker 
asn1_der_encode<T: Encode>(obj: &T) -> Result<Vec<u8>, der::Error>210*9860b763SAndroid Build Coastguard Worker pub(crate) fn asn1_der_encode<T: Encode>(obj: &T) -> Result<Vec<u8>, der::Error> {
211*9860b763SAndroid Build Coastguard Worker     let mut encoded_data = Vec::<u8>::new();
212*9860b763SAndroid Build Coastguard Worker     obj.encode_to_vec(&mut encoded_data)?;
213*9860b763SAndroid Build Coastguard Worker     Ok(encoded_data)
214*9860b763SAndroid Build Coastguard Worker }
215*9860b763SAndroid Build Coastguard Worker 
216*9860b763SAndroid Build Coastguard Worker /// Build key usage extension bits.
key_usage_extension_bits(params: &[KeyParam]) -> KeyUsage217*9860b763SAndroid Build Coastguard Worker pub(crate) fn key_usage_extension_bits(params: &[KeyParam]) -> KeyUsage {
218*9860b763SAndroid Build Coastguard Worker     // Build `KeyUsage` bitmask based on allowed purposes for the key.
219*9860b763SAndroid Build Coastguard Worker     let mut key_usage_bits = FlagSet::<KeyUsages>::default();
220*9860b763SAndroid Build Coastguard Worker     for param in params {
221*9860b763SAndroid Build Coastguard Worker         if let KeyParam::Purpose(purpose) = param {
222*9860b763SAndroid Build Coastguard Worker             match purpose {
223*9860b763SAndroid Build Coastguard Worker                 KeyPurpose::Sign | KeyPurpose::Verify => {
224*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::DigitalSignature;
225*9860b763SAndroid Build Coastguard Worker                 }
226*9860b763SAndroid Build Coastguard Worker                 KeyPurpose::Decrypt | KeyPurpose::Encrypt => {
227*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::DataEncipherment;
228*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::KeyEncipherment;
229*9860b763SAndroid Build Coastguard Worker                 }
230*9860b763SAndroid Build Coastguard Worker                 KeyPurpose::WrapKey => {
231*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::KeyEncipherment;
232*9860b763SAndroid Build Coastguard Worker                 }
233*9860b763SAndroid Build Coastguard Worker                 KeyPurpose::AgreeKey => {
234*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::KeyAgreement;
235*9860b763SAndroid Build Coastguard Worker                 }
236*9860b763SAndroid Build Coastguard Worker                 KeyPurpose::AttestKey => {
237*9860b763SAndroid Build Coastguard Worker                     key_usage_bits |= KeyUsages::KeyCertSign;
238*9860b763SAndroid Build Coastguard Worker                 }
239*9860b763SAndroid Build Coastguard Worker             }
240*9860b763SAndroid Build Coastguard Worker         }
241*9860b763SAndroid Build Coastguard Worker     }
242*9860b763SAndroid Build Coastguard Worker     KeyUsage(key_usage_bits)
243*9860b763SAndroid Build Coastguard Worker }
244*9860b763SAndroid Build Coastguard Worker 
245*9860b763SAndroid Build Coastguard Worker /// Build basic constraints extension value
basic_constraints_ext_value(ca_required: bool) -> BasicConstraints246*9860b763SAndroid Build Coastguard Worker pub(crate) fn basic_constraints_ext_value(ca_required: bool) -> BasicConstraints {
247*9860b763SAndroid Build Coastguard Worker     BasicConstraints { ca: ca_required, path_len_constraint: None }
248*9860b763SAndroid Build Coastguard Worker }
249*9860b763SAndroid Build Coastguard Worker 
250*9860b763SAndroid Build Coastguard Worker /// Attestation extension contents
251*9860b763SAndroid Build Coastguard Worker ///
252*9860b763SAndroid Build Coastguard Worker /// ```asn1
253*9860b763SAndroid Build Coastguard Worker /// KeyDescription ::= SEQUENCE {
254*9860b763SAndroid Build Coastguard Worker ///     attestationVersion         INTEGER,
255*9860b763SAndroid Build Coastguard Worker ///     attestationSecurityLevel   SecurityLevel,
256*9860b763SAndroid Build Coastguard Worker ///     keyMintVersion             INTEGER,
257*9860b763SAndroid Build Coastguard Worker ///     keymintSecurityLevel       SecurityLevel,
258*9860b763SAndroid Build Coastguard Worker ///     attestationChallenge       OCTET_STRING,
259*9860b763SAndroid Build Coastguard Worker ///     uniqueId                   OCTET_STRING,
260*9860b763SAndroid Build Coastguard Worker ///     softwareEnforced           AuthorizationList,
261*9860b763SAndroid Build Coastguard Worker ///     hardwareEnforced           AuthorizationList,
262*9860b763SAndroid Build Coastguard Worker /// }
263*9860b763SAndroid Build Coastguard Worker /// ```
264*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Sequence, PartialEq)]
265*9860b763SAndroid Build Coastguard Worker pub struct AttestationExtension<'a> {
266*9860b763SAndroid Build Coastguard Worker     attestation_version: i32,
267*9860b763SAndroid Build Coastguard Worker     attestation_security_level: SecurityLevel,
268*9860b763SAndroid Build Coastguard Worker     keymint_version: i32,
269*9860b763SAndroid Build Coastguard Worker     keymint_security_level: SecurityLevel,
270*9860b763SAndroid Build Coastguard Worker     #[asn1(type = "OCTET STRING")]
271*9860b763SAndroid Build Coastguard Worker     attestation_challenge: &'a [u8],
272*9860b763SAndroid Build Coastguard Worker     #[asn1(type = "OCTET STRING")]
273*9860b763SAndroid Build Coastguard Worker     unique_id: &'a [u8],
274*9860b763SAndroid Build Coastguard Worker     sw_enforced: AuthorizationList<'a>,
275*9860b763SAndroid Build Coastguard Worker     hw_enforced: AuthorizationList<'a>,
276*9860b763SAndroid Build Coastguard Worker }
277*9860b763SAndroid Build Coastguard Worker 
278*9860b763SAndroid Build Coastguard Worker impl<'a> AssociatedOid for AttestationExtension<'a> {
279*9860b763SAndroid Build Coastguard Worker     const OID: ObjectIdentifier = ATTESTATION_EXTENSION_OID;
280*9860b763SAndroid Build Coastguard Worker }
281*9860b763SAndroid Build Coastguard Worker 
282*9860b763SAndroid Build Coastguard Worker /// Security level enumeration
283*9860b763SAndroid Build Coastguard Worker /// ```asn1
284*9860b763SAndroid Build Coastguard Worker /// SecurityLevel ::= ENUMERATED {
285*9860b763SAndroid Build Coastguard Worker ///     Software                   (0),
286*9860b763SAndroid Build Coastguard Worker ///     TrustedEnvironment         (1),
287*9860b763SAndroid Build Coastguard Worker ///     StrongBox                  (2),
288*9860b763SAndroid Build Coastguard Worker /// }
289*9860b763SAndroid Build Coastguard Worker /// ```
290*9860b763SAndroid Build Coastguard Worker #[repr(u32)]
291*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Enumerated, PartialEq)]
292*9860b763SAndroid Build Coastguard Worker enum SecurityLevel {
293*9860b763SAndroid Build Coastguard Worker     Software = 0,
294*9860b763SAndroid Build Coastguard Worker     TrustedEnvironment = 1,
295*9860b763SAndroid Build Coastguard Worker     Strongbox = 2,
296*9860b763SAndroid Build Coastguard Worker }
297*9860b763SAndroid Build Coastguard Worker 
298*9860b763SAndroid Build Coastguard Worker /// Build an ASN.1 DER-encoded attestation extension.
299*9860b763SAndroid Build Coastguard Worker #[allow(clippy::too_many_arguments)]
attestation_extension<'a>( keymint_version: i32, challenge: &'a [u8], app_id: &'a [u8], security_level: keymint::SecurityLevel, attestation_ids: Option<&'a crate::AttestationIdInfo>, params: &'a [KeyParam], chars: &'a [KeyCharacteristics], unique_id: &'a Vec<u8>, boot_info: &'a keymint::BootInfo, additional_attestation_info: &'a [KeyParam], ) -> Result<AttestationExtension<'a>, Error>300*9860b763SAndroid Build Coastguard Worker pub(crate) fn attestation_extension<'a>(
301*9860b763SAndroid Build Coastguard Worker     keymint_version: i32,
302*9860b763SAndroid Build Coastguard Worker     challenge: &'a [u8],
303*9860b763SAndroid Build Coastguard Worker     app_id: &'a [u8],
304*9860b763SAndroid Build Coastguard Worker     security_level: keymint::SecurityLevel,
305*9860b763SAndroid Build Coastguard Worker     attestation_ids: Option<&'a crate::AttestationIdInfo>,
306*9860b763SAndroid Build Coastguard Worker     params: &'a [KeyParam],
307*9860b763SAndroid Build Coastguard Worker     chars: &'a [KeyCharacteristics],
308*9860b763SAndroid Build Coastguard Worker     unique_id: &'a Vec<u8>,
309*9860b763SAndroid Build Coastguard Worker     boot_info: &'a keymint::BootInfo,
310*9860b763SAndroid Build Coastguard Worker     additional_attestation_info: &'a [KeyParam],
311*9860b763SAndroid Build Coastguard Worker ) -> Result<AttestationExtension<'a>, Error> {
312*9860b763SAndroid Build Coastguard Worker     let mut sw_chars: &[KeyParam] = &[];
313*9860b763SAndroid Build Coastguard Worker     let mut hw_chars: &[KeyParam] = &[];
314*9860b763SAndroid Build Coastguard Worker     for characteristic in chars.iter() {
315*9860b763SAndroid Build Coastguard Worker         match characteristic.security_level {
316*9860b763SAndroid Build Coastguard Worker             keymint::SecurityLevel::Keystore | keymint::SecurityLevel::Software => {
317*9860b763SAndroid Build Coastguard Worker                 sw_chars = &characteristic.authorizations
318*9860b763SAndroid Build Coastguard Worker             }
319*9860b763SAndroid Build Coastguard Worker             l if l == security_level => hw_chars = &characteristic.authorizations,
320*9860b763SAndroid Build Coastguard Worker             l => {
321*9860b763SAndroid Build Coastguard Worker                 return Err(km_err!(
322*9860b763SAndroid Build Coastguard Worker                     InvalidTag,
323*9860b763SAndroid Build Coastguard Worker                     "found characteristics for unexpected security level {:?}",
324*9860b763SAndroid Build Coastguard Worker                     l,
325*9860b763SAndroid Build Coastguard Worker                 ))
326*9860b763SAndroid Build Coastguard Worker             }
327*9860b763SAndroid Build Coastguard Worker         }
328*9860b763SAndroid Build Coastguard Worker     }
329*9860b763SAndroid Build Coastguard Worker     let (sw_params, hw_params): (&[KeyParam], &[KeyParam]) = match security_level {
330*9860b763SAndroid Build Coastguard Worker         keymint::SecurityLevel::Software => (params, &[]),
331*9860b763SAndroid Build Coastguard Worker         _ => (&[], params),
332*9860b763SAndroid Build Coastguard Worker     };
333*9860b763SAndroid Build Coastguard Worker     let sw_enforced = AuthorizationList::new(
334*9860b763SAndroid Build Coastguard Worker         sw_chars,
335*9860b763SAndroid Build Coastguard Worker         sw_params,
336*9860b763SAndroid Build Coastguard Worker         attestation_ids,
337*9860b763SAndroid Build Coastguard Worker         None,
338*9860b763SAndroid Build Coastguard Worker         Some(app_id),
339*9860b763SAndroid Build Coastguard Worker         additional_attestation_info,
340*9860b763SAndroid Build Coastguard Worker     )?;
341*9860b763SAndroid Build Coastguard Worker     let hw_enforced = AuthorizationList::new(
342*9860b763SAndroid Build Coastguard Worker         hw_chars,
343*9860b763SAndroid Build Coastguard Worker         hw_params,
344*9860b763SAndroid Build Coastguard Worker         attestation_ids,
345*9860b763SAndroid Build Coastguard Worker         Some(RootOfTrust::from(boot_info)),
346*9860b763SAndroid Build Coastguard Worker         None,
347*9860b763SAndroid Build Coastguard Worker         &[],
348*9860b763SAndroid Build Coastguard Worker     )?;
349*9860b763SAndroid Build Coastguard Worker     let sec_level = SecurityLevel::try_from(security_level as u32)
350*9860b763SAndroid Build Coastguard Worker         .map_err(|_| km_err!(InvalidArgument, "invalid security level {:?}", security_level))?;
351*9860b763SAndroid Build Coastguard Worker     let ext = AttestationExtension {
352*9860b763SAndroid Build Coastguard Worker         attestation_version: keymint_version,
353*9860b763SAndroid Build Coastguard Worker         attestation_security_level: sec_level,
354*9860b763SAndroid Build Coastguard Worker         keymint_version,
355*9860b763SAndroid Build Coastguard Worker         keymint_security_level: sec_level,
356*9860b763SAndroid Build Coastguard Worker         attestation_challenge: challenge,
357*9860b763SAndroid Build Coastguard Worker         unique_id,
358*9860b763SAndroid Build Coastguard Worker         sw_enforced,
359*9860b763SAndroid Build Coastguard Worker         hw_enforced,
360*9860b763SAndroid Build Coastguard Worker     };
361*9860b763SAndroid Build Coastguard Worker     Ok(ext)
362*9860b763SAndroid Build Coastguard Worker }
363*9860b763SAndroid Build Coastguard Worker 
364*9860b763SAndroid Build Coastguard Worker /// Struct for creating ASN.1 DER-serialized `AuthorizationList`. The fields in the ASN.1
365*9860b763SAndroid Build Coastguard Worker /// sequence are categorized into four fields in the struct based on their usage.
366*9860b763SAndroid Build Coastguard Worker /// ```asn1
367*9860b763SAndroid Build Coastguard Worker /// AuthorizationList ::= SEQUENCE {
368*9860b763SAndroid Build Coastguard Worker ///     purpose                    [1] EXPLICIT SET OF INTEGER OPTIONAL,
369*9860b763SAndroid Build Coastguard Worker ///     algorithm                  [2] EXPLICIT INTEGER OPTIONAL,
370*9860b763SAndroid Build Coastguard Worker ///     keySize                    [3] EXPLICIT INTEGER OPTIONAL,
371*9860b763SAndroid Build Coastguard Worker ///     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL,  -- Symmetric keys only
372*9860b763SAndroid Build Coastguard Worker ///     digest                     [5] EXPLICIT SET OF INTEGER OPTIONAL,
373*9860b763SAndroid Build Coastguard Worker ///     padding                    [6] EXPLICIT SET OF INTEGER OPTIONAL,
374*9860b763SAndroid Build Coastguard Worker ///     callerNonce                [7] EXPLICIT NULL OPTIONAL,  -- Symmetric keys only
375*9860b763SAndroid Build Coastguard Worker ///     minMacLength               [8] EXPLICIT INTEGER OPTIONAL,  -- Symmetric keys only
376*9860b763SAndroid Build Coastguard Worker ///     ecCurve                    [10] EXPLICIT INTEGER OPTIONAL,
377*9860b763SAndroid Build Coastguard Worker ///     rsaPublicExponent          [200] EXPLICIT INTEGER OPTIONAL,
378*9860b763SAndroid Build Coastguard Worker ///     mgfDigest                  [203] EXPLICIT SET OF INTEGER OPTIONAL,
379*9860b763SAndroid Build Coastguard Worker ///     rollbackResistance         [303] EXPLICIT NULL OPTIONAL,
380*9860b763SAndroid Build Coastguard Worker ///     earlyBootOnly              [305] EXPLICIT NULL OPTIONAL,
381*9860b763SAndroid Build Coastguard Worker ///     activeDateTime             [400] EXPLICIT INTEGER OPTIONAL,
382*9860b763SAndroid Build Coastguard Worker ///     originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
383*9860b763SAndroid Build Coastguard Worker ///     usageExpireDateTime        [402] EXPLICIT INTEGER OPTIONAL,
384*9860b763SAndroid Build Coastguard Worker ///     usageCountLimit            [405] EXPLICIT INTEGER OPTIONAL,
385*9860b763SAndroid Build Coastguard Worker ///     userSecureId               [502] EXPLICIT INTEGER OPTIONAL,  -- Only used on key import
386*9860b763SAndroid Build Coastguard Worker ///     noAuthRequired             [503] EXPLICIT NULL OPTIONAL,
387*9860b763SAndroid Build Coastguard Worker ///     userAuthType               [504] EXPLICIT INTEGER OPTIONAL,
388*9860b763SAndroid Build Coastguard Worker ///     authTimeout                [505] EXPLICIT INTEGER OPTIONAL,
389*9860b763SAndroid Build Coastguard Worker ///     allowWhileOnBody           [506] EXPLICIT NULL OPTIONAL,
390*9860b763SAndroid Build Coastguard Worker ///     trustedUserPresenceReq     [507] EXPLICIT NULL OPTIONAL,
391*9860b763SAndroid Build Coastguard Worker ///     trustedConfirmationReq     [508] EXPLICIT NULL OPTIONAL,
392*9860b763SAndroid Build Coastguard Worker ///     unlockedDeviceReq          [509] EXPLICIT NULL OPTIONAL,
393*9860b763SAndroid Build Coastguard Worker ///     creationDateTime           [701] EXPLICIT INTEGER OPTIONAL,
394*9860b763SAndroid Build Coastguard Worker ///     origin                     [702] EXPLICIT INTEGER OPTIONAL,
395*9860b763SAndroid Build Coastguard Worker ///     rootOfTrust                [704] EXPLICIT RootOfTrust OPTIONAL,
396*9860b763SAndroid Build Coastguard Worker ///     osVersion                  [705] EXPLICIT INTEGER OPTIONAL,
397*9860b763SAndroid Build Coastguard Worker ///     osPatchLevel               [706] EXPLICIT INTEGER OPTIONAL,
398*9860b763SAndroid Build Coastguard Worker ///     attestationApplicationId   [709] EXPLICIT OCTET_STRING OPTIONAL,
399*9860b763SAndroid Build Coastguard Worker ///     attestationIdBrand         [710] EXPLICIT OCTET_STRING OPTIONAL,
400*9860b763SAndroid Build Coastguard Worker ///     attestationIdDevice        [711] EXPLICIT OCTET_STRING OPTIONAL,
401*9860b763SAndroid Build Coastguard Worker ///     attestationIdProduct       [712] EXPLICIT OCTET_STRING OPTIONAL,
402*9860b763SAndroid Build Coastguard Worker ///     attestationIdSerial        [713] EXPLICIT OCTET_STRING OPTIONAL,
403*9860b763SAndroid Build Coastguard Worker ///     attestationIdImei          [714] EXPLICIT OCTET_STRING OPTIONAL,
404*9860b763SAndroid Build Coastguard Worker ///     attestationIdMeid          [715] EXPLICIT OCTET_STRING OPTIONAL,
405*9860b763SAndroid Build Coastguard Worker ///     attestationIdManufacturer  [716] EXPLICIT OCTET_STRING OPTIONAL,
406*9860b763SAndroid Build Coastguard Worker ///     attestationIdModel         [717] EXPLICIT OCTET_STRING OPTIONAL,
407*9860b763SAndroid Build Coastguard Worker ///     vendorPatchLevel           [718] EXPLICIT INTEGER OPTIONAL,
408*9860b763SAndroid Build Coastguard Worker ///     bootPatchLevel             [719] EXPLICIT INTEGER OPTIONAL,
409*9860b763SAndroid Build Coastguard Worker ///     deviceUniqueAttestation    [720] EXPLICIT NULL OPTIONAL,
410*9860b763SAndroid Build Coastguard Worker ///     attestationIdSecondImei    [723] EXPLICIT OCTET_STRING OPTIONAL,
411*9860b763SAndroid Build Coastguard Worker ///     -- moduleHash contains a SHA-256 hash of DER-encoded `Modules`
412*9860b763SAndroid Build Coastguard Worker ///     moduleHash                 [724] EXPLICIT OCTET_STRING OPTIONAL,
413*9860b763SAndroid Build Coastguard Worker /// }
414*9860b763SAndroid Build Coastguard Worker /// ```
415*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq)]
416*9860b763SAndroid Build Coastguard Worker pub struct AuthorizationList<'a> {
417*9860b763SAndroid Build Coastguard Worker     pub auths: Cow<'a, [KeyParam]>,
418*9860b763SAndroid Build Coastguard Worker     pub keygen_params: Cow<'a, [KeyParam]>,
419*9860b763SAndroid Build Coastguard Worker     pub rot_info: Option<KeyParam>,
420*9860b763SAndroid Build Coastguard Worker     pub app_id: Option<KeyParam>,
421*9860b763SAndroid Build Coastguard Worker     pub additional_attestation_info: Cow<'a, [KeyParam]>,
422*9860b763SAndroid Build Coastguard Worker }
423*9860b763SAndroid Build Coastguard Worker 
424*9860b763SAndroid Build Coastguard Worker /// Macro to check that a specified attestation ID matches the provisioned value.
425*9860b763SAndroid Build Coastguard Worker macro_rules! check_attestation_id {
426*9860b763SAndroid Build Coastguard Worker     {
427*9860b763SAndroid Build Coastguard Worker         $params:expr, $variant:ident, $mustmatch:expr
428*9860b763SAndroid Build Coastguard Worker     } => {
429*9860b763SAndroid Build Coastguard Worker         {
430*9860b763SAndroid Build Coastguard Worker             if let Some(val) = get_opt_tag_value!($params, $variant)? {
431*9860b763SAndroid Build Coastguard Worker                 match $mustmatch {
432*9860b763SAndroid Build Coastguard Worker                     None => return Err(km_err!(CannotAttestIds,
433*9860b763SAndroid Build Coastguard Worker                                                "no attestation IDs provisioned")),
434*9860b763SAndroid Build Coastguard Worker                     Some(want)  => if val != want {
435*9860b763SAndroid Build Coastguard Worker                         return Err(km_err!(CannotAttestIds,
436*9860b763SAndroid Build Coastguard Worker                                            "attestation ID mismatch for {}",
437*9860b763SAndroid Build Coastguard Worker                                            stringify!($variant)))
438*9860b763SAndroid Build Coastguard Worker                     }
439*9860b763SAndroid Build Coastguard Worker                 }
440*9860b763SAndroid Build Coastguard Worker             }
441*9860b763SAndroid Build Coastguard Worker         }
442*9860b763SAndroid Build Coastguard Worker     }
443*9860b763SAndroid Build Coastguard Worker }
444*9860b763SAndroid Build Coastguard Worker 
445*9860b763SAndroid Build Coastguard Worker impl<'a> AuthorizationList<'a> {
446*9860b763SAndroid Build Coastguard Worker     /// Build an `AuthorizationList` ready for serialization. This constructor will fail if device
447*9860b763SAndroid Build Coastguard Worker     /// ID attestation is required but the relevant IDs are missing or mismatched.
new( auths: &'a [KeyParam], keygen_params: &'a [KeyParam], attestation_ids: Option<&'a crate::AttestationIdInfo>, rot_info: Option<RootOfTrust<'a>>, app_id: Option<&'a [u8]>, additional_attestation_info: &'a [KeyParam], ) -> Result<Self, Error>448*9860b763SAndroid Build Coastguard Worker     fn new(
449*9860b763SAndroid Build Coastguard Worker         auths: &'a [KeyParam],
450*9860b763SAndroid Build Coastguard Worker         keygen_params: &'a [KeyParam],
451*9860b763SAndroid Build Coastguard Worker         attestation_ids: Option<&'a crate::AttestationIdInfo>,
452*9860b763SAndroid Build Coastguard Worker         rot_info: Option<RootOfTrust<'a>>,
453*9860b763SAndroid Build Coastguard Worker         app_id: Option<&'a [u8]>,
454*9860b763SAndroid Build Coastguard Worker         additional_attestation_info: &'a [KeyParam],
455*9860b763SAndroid Build Coastguard Worker     ) -> Result<Self, Error> {
456*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(keygen_params, AttestationIdBrand, attestation_ids.map(|v| &v.brand));
457*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(
458*9860b763SAndroid Build Coastguard Worker             keygen_params,
459*9860b763SAndroid Build Coastguard Worker             AttestationIdDevice,
460*9860b763SAndroid Build Coastguard Worker             attestation_ids.map(|v| &v.device)
461*9860b763SAndroid Build Coastguard Worker         );
462*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(
463*9860b763SAndroid Build Coastguard Worker             keygen_params,
464*9860b763SAndroid Build Coastguard Worker             AttestationIdProduct,
465*9860b763SAndroid Build Coastguard Worker             attestation_ids.map(|v| &v.product)
466*9860b763SAndroid Build Coastguard Worker         );
467*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(
468*9860b763SAndroid Build Coastguard Worker             keygen_params,
469*9860b763SAndroid Build Coastguard Worker             AttestationIdSerial,
470*9860b763SAndroid Build Coastguard Worker             attestation_ids.map(|v| &v.serial)
471*9860b763SAndroid Build Coastguard Worker         );
472*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(keygen_params, AttestationIdImei, attestation_ids.map(|v| &v.imei));
473*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(
474*9860b763SAndroid Build Coastguard Worker             keygen_params,
475*9860b763SAndroid Build Coastguard Worker             AttestationIdSecondImei,
476*9860b763SAndroid Build Coastguard Worker             attestation_ids.map(|v| &v.imei2)
477*9860b763SAndroid Build Coastguard Worker         );
478*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(keygen_params, AttestationIdMeid, attestation_ids.map(|v| &v.meid));
479*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(
480*9860b763SAndroid Build Coastguard Worker             keygen_params,
481*9860b763SAndroid Build Coastguard Worker             AttestationIdManufacturer,
482*9860b763SAndroid Build Coastguard Worker             attestation_ids.map(|v| &v.manufacturer)
483*9860b763SAndroid Build Coastguard Worker         );
484*9860b763SAndroid Build Coastguard Worker         check_attestation_id!(keygen_params, AttestationIdModel, attestation_ids.map(|v| &v.model));
485*9860b763SAndroid Build Coastguard Worker 
486*9860b763SAndroid Build Coastguard Worker         let encoded_rot = if let Some(rot) = rot_info {
487*9860b763SAndroid Build Coastguard Worker             Some(rot.to_der().map_err(|e| der_err!(e, "failed to encode RoT"))?)
488*9860b763SAndroid Build Coastguard Worker         } else {
489*9860b763SAndroid Build Coastguard Worker             None
490*9860b763SAndroid Build Coastguard Worker         };
491*9860b763SAndroid Build Coastguard Worker         Ok(Self {
492*9860b763SAndroid Build Coastguard Worker             auths: auths.into(),
493*9860b763SAndroid Build Coastguard Worker             keygen_params: keygen_params.into(),
494*9860b763SAndroid Build Coastguard Worker             rot_info: encoded_rot.map(KeyParam::RootOfTrust),
495*9860b763SAndroid Build Coastguard Worker             app_id: match app_id {
496*9860b763SAndroid Build Coastguard Worker                 Some(app_id) => Some(KeyParam::AttestationApplicationId(try_to_vec(app_id)?)),
497*9860b763SAndroid Build Coastguard Worker                 None => None,
498*9860b763SAndroid Build Coastguard Worker             },
499*9860b763SAndroid Build Coastguard Worker             additional_attestation_info: additional_attestation_info.into(),
500*9860b763SAndroid Build Coastguard Worker         })
501*9860b763SAndroid Build Coastguard Worker     }
502*9860b763SAndroid Build Coastguard Worker 
503*9860b763SAndroid Build Coastguard Worker     /// Build an `AuthorizationList` using a set of key parameters.
504*9860b763SAndroid Build Coastguard Worker     /// The checks for the attestation ids are not run here in contrast to `AuthorizationList::new`
505*9860b763SAndroid Build Coastguard Worker     /// because this method is used to construct an `AuthorizationList` in the decode path rather
506*9860b763SAndroid Build Coastguard Worker     /// than in the encode path. Note: decode path is currently used only by
507*9860b763SAndroid Build Coastguard Worker     /// `KeyMintTa::import_wrapped_key` functionality, which only uses `auth` field of
508*9860b763SAndroid Build Coastguard Worker     /// `AuthorizationList`. Decoding for the whole `AuthorizationList` is added here for the
509*9860b763SAndroid Build Coastguard Worker     /// completeness and anticipating a future use case of decoding the attestation extension from
510*9860b763SAndroid Build Coastguard Worker     /// an X.509 certificate.
new_from_key_params(key_params: Vec<KeyParam>) -> Result<Self, der::Error>511*9860b763SAndroid Build Coastguard Worker     fn new_from_key_params(key_params: Vec<KeyParam>) -> Result<Self, der::Error> {
512*9860b763SAndroid Build Coastguard Worker         let mut auths = Vec::new();
513*9860b763SAndroid Build Coastguard Worker         let mut keygen_params = Vec::new();
514*9860b763SAndroid Build Coastguard Worker         let mut rot: Option<KeyParam> = None;
515*9860b763SAndroid Build Coastguard Worker         let mut attest_app_id: Option<KeyParam> = None;
516*9860b763SAndroid Build Coastguard Worker         let mut additional_attestation_info = Vec::new();
517*9860b763SAndroid Build Coastguard Worker 
518*9860b763SAndroid Build Coastguard Worker         // Divide key parameters into key characteristics and key generation parameters.
519*9860b763SAndroid Build Coastguard Worker         for param in key_params {
520*9860b763SAndroid Build Coastguard Worker             match param {
521*9860b763SAndroid Build Coastguard Worker                 KeyParam::RootOfTrust(_) => rot = Some(param),
522*9860b763SAndroid Build Coastguard Worker                 KeyParam::AttestationApplicationId(_) => attest_app_id = Some(param),
523*9860b763SAndroid Build Coastguard Worker                 KeyParam::AttestationIdBrand(_)
524*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdDevice(_)
525*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdProduct(_)
526*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdSerial(_)
527*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdImei(_)
528*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdSecondImei(_)
529*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdMeid(_)
530*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdManufacturer(_)
531*9860b763SAndroid Build Coastguard Worker                 | KeyParam::AttestationIdModel(_) => {
532*9860b763SAndroid Build Coastguard Worker                     keygen_params.try_push(param).map_err(der_alloc_err)?
533*9860b763SAndroid Build Coastguard Worker                 }
534*9860b763SAndroid Build Coastguard Worker                 KeyParam::ModuleHash(_) => {
535*9860b763SAndroid Build Coastguard Worker                     additional_attestation_info.try_push(param).map_err(der_alloc_err)?
536*9860b763SAndroid Build Coastguard Worker                 }
537*9860b763SAndroid Build Coastguard Worker                 _ => auths.try_push(param).map_err(der_alloc_err)?,
538*9860b763SAndroid Build Coastguard Worker             }
539*9860b763SAndroid Build Coastguard Worker         }
540*9860b763SAndroid Build Coastguard Worker         Ok(AuthorizationList {
541*9860b763SAndroid Build Coastguard Worker             auths: auths.into(),
542*9860b763SAndroid Build Coastguard Worker             keygen_params: keygen_params.into(),
543*9860b763SAndroid Build Coastguard Worker             rot_info: rot,
544*9860b763SAndroid Build Coastguard Worker             app_id: attest_app_id,
545*9860b763SAndroid Build Coastguard Worker             additional_attestation_info: additional_attestation_info.into(),
546*9860b763SAndroid Build Coastguard Worker         })
547*9860b763SAndroid Build Coastguard Worker     }
548*9860b763SAndroid Build Coastguard Worker }
549*9860b763SAndroid Build Coastguard Worker 
550*9860b763SAndroid Build Coastguard Worker /// Convert an error into a `der::Error` indicating allocation failure.
551*9860b763SAndroid Build Coastguard Worker #[inline]
der_alloc_err<T>(_e: T) -> der::Error552*9860b763SAndroid Build Coastguard Worker fn der_alloc_err<T>(_e: T) -> der::Error {
553*9860b763SAndroid Build Coastguard Worker     der::Error::new(der::ErrorKind::Overlength, der::Length::ZERO)
554*9860b763SAndroid Build Coastguard Worker }
555*9860b763SAndroid Build Coastguard Worker 
556*9860b763SAndroid Build Coastguard Worker /// All the fields of AuthorizationList sequence are optional. Therefore, the expected tag and the
557*9860b763SAndroid Build Coastguard Worker /// decoded tag might be different. If they don't match, return the decoded tag to be used in a
558*9860b763SAndroid Build Coastguard Worker /// future call to this method. If the two tags match, continue to read the value,
559*9860b763SAndroid Build Coastguard Worker /// populate key parameters and return None, so that the next call to this method will
560*9860b763SAndroid Build Coastguard Worker /// decode the tag from bytes. See the implementation of [`der::DecodeValue`] trait for
561*9860b763SAndroid Build Coastguard Worker /// AuthorizationList.
decode_opt_field<'a, R: der::Reader<'a>>( decoder: &mut R, already_read_tag: Option<keymint::Tag>, expected_tag: keymint::Tag, key_params: &mut Vec<KeyParam>, ) -> Result<Option<keymint::Tag>, der::Error>562*9860b763SAndroid Build Coastguard Worker fn decode_opt_field<'a, R: der::Reader<'a>>(
563*9860b763SAndroid Build Coastguard Worker     decoder: &mut R,
564*9860b763SAndroid Build Coastguard Worker     already_read_tag: Option<keymint::Tag>,
565*9860b763SAndroid Build Coastguard Worker     expected_tag: keymint::Tag,
566*9860b763SAndroid Build Coastguard Worker     key_params: &mut Vec<KeyParam>,
567*9860b763SAndroid Build Coastguard Worker ) -> Result<Option<keymint::Tag>, der::Error> {
568*9860b763SAndroid Build Coastguard Worker     // Decode the tag if no tag is provided
569*9860b763SAndroid Build Coastguard Worker     let tag =
570*9860b763SAndroid Build Coastguard Worker         if already_read_tag.is_none() { decode_tag_from_bytes(decoder)? } else { already_read_tag };
571*9860b763SAndroid Build Coastguard Worker     match tag {
572*9860b763SAndroid Build Coastguard Worker         Some(tag) if tag == expected_tag => {
573*9860b763SAndroid Build Coastguard Worker             // Decode the length of the inner encoding
574*9860b763SAndroid Build Coastguard Worker             let inner_len = Length::decode(decoder)?;
575*9860b763SAndroid Build Coastguard Worker             if decoder.remaining_len() < inner_len {
576*9860b763SAndroid Build Coastguard Worker                 return Err(der::ErrorKind::Incomplete {
577*9860b763SAndroid Build Coastguard Worker                     expected_len: inner_len,
578*9860b763SAndroid Build Coastguard Worker                     actual_len: decoder.remaining_len(),
579*9860b763SAndroid Build Coastguard Worker                 }
580*9860b763SAndroid Build Coastguard Worker                 .into());
581*9860b763SAndroid Build Coastguard Worker             }
582*9860b763SAndroid Build Coastguard Worker             let next_tlv = decoder.tlv_bytes()?;
583*9860b763SAndroid Build Coastguard Worker             decode_value_from_bytes(expected_tag, next_tlv, key_params)?;
584*9860b763SAndroid Build Coastguard Worker             Ok(None)
585*9860b763SAndroid Build Coastguard Worker         }
586*9860b763SAndroid Build Coastguard Worker         Some(tag) => Ok(Some(tag)), // Return the tag for which the value is unread.
587*9860b763SAndroid Build Coastguard Worker         None => Ok(None),
588*9860b763SAndroid Build Coastguard Worker     }
589*9860b763SAndroid Build Coastguard Worker }
590*9860b763SAndroid Build Coastguard Worker 
591*9860b763SAndroid Build Coastguard Worker macro_rules! process_authz_list_tags {
592*9860b763SAndroid Build Coastguard Worker     {$decoder:expr, $key_params:expr, ($($tag:ident),*)} => {
593*9860b763SAndroid Build Coastguard Worker         let mut non_consumed_tag: Option<Tag> = None;
594*9860b763SAndroid Build Coastguard Worker         ($(non_consumed_tag = decode_opt_field($decoder,
595*9860b763SAndroid Build Coastguard Worker                                                non_consumed_tag,
596*9860b763SAndroid Build Coastguard Worker                                                Tag::$tag,
597*9860b763SAndroid Build Coastguard Worker                                                $key_params)?),*);
598*9860b763SAndroid Build Coastguard Worker         if non_consumed_tag.is_some(){
599*9860b763SAndroid Build Coastguard Worker             return Err($decoder.error(der::ErrorKind::Incomplete {
600*9860b763SAndroid Build Coastguard Worker                 expected_len: Length::ZERO,
601*9860b763SAndroid Build Coastguard Worker                 actual_len: $decoder.remaining_len(),
602*9860b763SAndroid Build Coastguard Worker             }));
603*9860b763SAndroid Build Coastguard Worker         }
604*9860b763SAndroid Build Coastguard Worker     };
605*9860b763SAndroid Build Coastguard Worker }
606*9860b763SAndroid Build Coastguard Worker 
607*9860b763SAndroid Build Coastguard Worker /// Implementation of [`der::DecodeValue`] which constructs an AuthorizationList from bytes.
608*9860b763SAndroid Build Coastguard Worker impl<'a> der::DecodeValue<'a> for AuthorizationList<'a> {
decode_value<R: der::Reader<'a>>(decoder: &mut R, header: der::Header) -> der::Result<Self>609*9860b763SAndroid Build Coastguard Worker     fn decode_value<R: der::Reader<'a>>(decoder: &mut R, header: der::Header) -> der::Result<Self> {
610*9860b763SAndroid Build Coastguard Worker         // TODO: define a MAX_SIZE for AuthorizationList and check whether the actual length from
611*9860b763SAndroid Build Coastguard Worker         // the length field of header is less than the MAX_SIZE
612*9860b763SAndroid Build Coastguard Worker 
613*9860b763SAndroid Build Coastguard Worker         // Check for an empty sequence
614*9860b763SAndroid Build Coastguard Worker         if header.length.is_zero() {
615*9860b763SAndroid Build Coastguard Worker             return Ok(AuthorizationList {
616*9860b763SAndroid Build Coastguard Worker                 auths: Vec::new().into(),
617*9860b763SAndroid Build Coastguard Worker                 keygen_params: Vec::new().into(),
618*9860b763SAndroid Build Coastguard Worker                 rot_info: None,
619*9860b763SAndroid Build Coastguard Worker                 app_id: None,
620*9860b763SAndroid Build Coastguard Worker                 additional_attestation_info: Vec::new().into(),
621*9860b763SAndroid Build Coastguard Worker             });
622*9860b763SAndroid Build Coastguard Worker         }
623*9860b763SAndroid Build Coastguard Worker         if decoder.remaining_len() < header.length {
624*9860b763SAndroid Build Coastguard Worker             return Err(der::ErrorKind::Incomplete {
625*9860b763SAndroid Build Coastguard Worker                 expected_len: header.length,
626*9860b763SAndroid Build Coastguard Worker                 actual_len: decoder.remaining_len(),
627*9860b763SAndroid Build Coastguard Worker             })?;
628*9860b763SAndroid Build Coastguard Worker         }
629*9860b763SAndroid Build Coastguard Worker         let mut key_params = Vec::new();
630*9860b763SAndroid Build Coastguard Worker         process_authz_list_tags!(
631*9860b763SAndroid Build Coastguard Worker             decoder,
632*9860b763SAndroid Build Coastguard Worker             &mut key_params,
633*9860b763SAndroid Build Coastguard Worker             (
634*9860b763SAndroid Build Coastguard Worker                 Purpose,
635*9860b763SAndroid Build Coastguard Worker                 Algorithm,
636*9860b763SAndroid Build Coastguard Worker                 KeySize,
637*9860b763SAndroid Build Coastguard Worker                 BlockMode,
638*9860b763SAndroid Build Coastguard Worker                 Digest,
639*9860b763SAndroid Build Coastguard Worker                 Padding,
640*9860b763SAndroid Build Coastguard Worker                 CallerNonce,
641*9860b763SAndroid Build Coastguard Worker                 MinMacLength,
642*9860b763SAndroid Build Coastguard Worker                 EcCurve,
643*9860b763SAndroid Build Coastguard Worker                 RsaPublicExponent,
644*9860b763SAndroid Build Coastguard Worker                 RsaOaepMgfDigest,
645*9860b763SAndroid Build Coastguard Worker                 RollbackResistance,
646*9860b763SAndroid Build Coastguard Worker                 EarlyBootOnly,
647*9860b763SAndroid Build Coastguard Worker                 ActiveDatetime,
648*9860b763SAndroid Build Coastguard Worker                 OriginationExpireDatetime,
649*9860b763SAndroid Build Coastguard Worker                 UsageExpireDatetime,
650*9860b763SAndroid Build Coastguard Worker                 UsageCountLimit,
651*9860b763SAndroid Build Coastguard Worker                 UserSecureId,
652*9860b763SAndroid Build Coastguard Worker                 NoAuthRequired,
653*9860b763SAndroid Build Coastguard Worker                 UserAuthType,
654*9860b763SAndroid Build Coastguard Worker                 AuthTimeout,
655*9860b763SAndroid Build Coastguard Worker                 AllowWhileOnBody,
656*9860b763SAndroid Build Coastguard Worker                 TrustedUserPresenceRequired,
657*9860b763SAndroid Build Coastguard Worker                 TrustedConfirmationRequired,
658*9860b763SAndroid Build Coastguard Worker                 UnlockedDeviceRequired,
659*9860b763SAndroid Build Coastguard Worker                 CreationDatetime,
660*9860b763SAndroid Build Coastguard Worker                 CreationDatetime,
661*9860b763SAndroid Build Coastguard Worker                 Origin,
662*9860b763SAndroid Build Coastguard Worker                 RootOfTrust,
663*9860b763SAndroid Build Coastguard Worker                 OsVersion,
664*9860b763SAndroid Build Coastguard Worker                 OsPatchlevel,
665*9860b763SAndroid Build Coastguard Worker                 AttestationApplicationId,
666*9860b763SAndroid Build Coastguard Worker                 AttestationIdBrand,
667*9860b763SAndroid Build Coastguard Worker                 AttestationIdDevice,
668*9860b763SAndroid Build Coastguard Worker                 AttestationIdProduct,
669*9860b763SAndroid Build Coastguard Worker                 AttestationIdSerial,
670*9860b763SAndroid Build Coastguard Worker                 AttestationIdSerial,
671*9860b763SAndroid Build Coastguard Worker                 AttestationIdSerial,
672*9860b763SAndroid Build Coastguard Worker                 AttestationIdImei,
673*9860b763SAndroid Build Coastguard Worker                 AttestationIdMeid,
674*9860b763SAndroid Build Coastguard Worker                 AttestationIdManufacturer,
675*9860b763SAndroid Build Coastguard Worker                 AttestationIdModel,
676*9860b763SAndroid Build Coastguard Worker                 VendorPatchlevel,
677*9860b763SAndroid Build Coastguard Worker                 BootPatchlevel,
678*9860b763SAndroid Build Coastguard Worker                 DeviceUniqueAttestation,
679*9860b763SAndroid Build Coastguard Worker                 AttestationIdSecondImei,
680*9860b763SAndroid Build Coastguard Worker                 ModuleHash
681*9860b763SAndroid Build Coastguard Worker             )
682*9860b763SAndroid Build Coastguard Worker         );
683*9860b763SAndroid Build Coastguard Worker 
684*9860b763SAndroid Build Coastguard Worker         // Process the key params and construct the `AuthorizationList`
685*9860b763SAndroid Build Coastguard Worker         AuthorizationList::new_from_key_params(key_params)
686*9860b763SAndroid Build Coastguard Worker     }
687*9860b763SAndroid Build Coastguard Worker }
688*9860b763SAndroid Build Coastguard Worker 
689*9860b763SAndroid Build Coastguard Worker // Macros to decode key parameters from their ASN.1 encoding in one of the forms:
690*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT SET OF INTEGER OPTIONAL
691*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT INTEGER OPTIONAL
692*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT NULL OPTIONAL
693*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT OCTET STRING OPTIONAL
694*9860b763SAndroid Build Coastguard Worker // There are three different variants for the INTEGER type.
695*9860b763SAndroid Build Coastguard Worker 
696*9860b763SAndroid Build Coastguard Worker macro_rules! key_params_from_asn1_set_of_integer {
697*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $tlv_bytes:expr, $key_params:expr} => {
698*9860b763SAndroid Build Coastguard Worker         let vals = SetOfVec::<i32>::from_der($tlv_bytes)?;
699*9860b763SAndroid Build Coastguard Worker         for val in vals.into_vec() {
700*9860b763SAndroid Build Coastguard Worker             $key_params.try_push(KeyParam::$variant(val.try_into().map_err(
701*9860b763SAndroid Build Coastguard Worker                 |_e| der::ErrorKind::Value {tag: der::Tag::Set})?)).map_err(der_alloc_err)?;
702*9860b763SAndroid Build Coastguard Worker         }
703*9860b763SAndroid Build Coastguard Worker     }
704*9860b763SAndroid Build Coastguard Worker }
705*9860b763SAndroid Build Coastguard Worker 
706*9860b763SAndroid Build Coastguard Worker macro_rules! key_param_from_asn1_integer {
707*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $int_type:ident, $tlv_bytes:expr, $key_params:expr} => {
708*9860b763SAndroid Build Coastguard Worker         let val = $int_type::from_der($tlv_bytes)?;
709*9860b763SAndroid Build Coastguard Worker         $key_params.try_push(KeyParam::$variant(val.try_into().map_err(
710*9860b763SAndroid Build Coastguard Worker                 |_e| der::ErrorKind::Value {tag: der::Tag::Integer})?)).map_err(der_alloc_err)?;
711*9860b763SAndroid Build Coastguard Worker     }
712*9860b763SAndroid Build Coastguard Worker }
713*9860b763SAndroid Build Coastguard Worker 
714*9860b763SAndroid Build Coastguard Worker macro_rules! key_param_from_asn1_integer_newtype {
715*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $int_type:ident, $newtype:ident, $tlv_bytes:expr, $key_params:expr} => {
716*9860b763SAndroid Build Coastguard Worker         let val = $int_type::from_der($tlv_bytes)?;
717*9860b763SAndroid Build Coastguard Worker         $key_params.try_push(KeyParam::$variant($newtype(val.try_into().map_err(
718*9860b763SAndroid Build Coastguard Worker                 |_e| der::ErrorKind::Value {tag: der::Tag::Integer})?))).map_err(der_alloc_err)?;
719*9860b763SAndroid Build Coastguard Worker     }
720*9860b763SAndroid Build Coastguard Worker }
721*9860b763SAndroid Build Coastguard Worker 
722*9860b763SAndroid Build Coastguard Worker macro_rules! key_param_from_asn1_null {
723*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $tlv_bytes:expr, $key_params:expr} => {
724*9860b763SAndroid Build Coastguard Worker         Null::from_der($tlv_bytes)?;
725*9860b763SAndroid Build Coastguard Worker         $key_params.try_push(KeyParam::$variant).map_err(der_alloc_err)?;
726*9860b763SAndroid Build Coastguard Worker     };
727*9860b763SAndroid Build Coastguard Worker }
728*9860b763SAndroid Build Coastguard Worker 
729*9860b763SAndroid Build Coastguard Worker macro_rules! key_param_from_asn1_integer_datetime {
730*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $tlv_bytes:expr, $key_params:expr} => {
731*9860b763SAndroid Build Coastguard Worker         let val = i64::from_der($tlv_bytes)?;
732*9860b763SAndroid Build Coastguard Worker         $key_params
733*9860b763SAndroid Build Coastguard Worker             .try_push(KeyParam::$variant(DateTime{ms_since_epoch: val}))
734*9860b763SAndroid Build Coastguard Worker             .map_err(der_alloc_err)?;
735*9860b763SAndroid Build Coastguard Worker     };
736*9860b763SAndroid Build Coastguard Worker }
737*9860b763SAndroid Build Coastguard Worker 
738*9860b763SAndroid Build Coastguard Worker macro_rules! key_param_from_asn1_octet_string {
739*9860b763SAndroid Build Coastguard Worker     {$variant:ident, $tlv_bytes:expr, $key_params:expr} => {
740*9860b763SAndroid Build Coastguard Worker         let val = OctetStringRef::from_der($tlv_bytes)?;
741*9860b763SAndroid Build Coastguard Worker         $key_params.try_push(KeyParam::$variant(try_to_vec(val.as_bytes())
742*9860b763SAndroid Build Coastguard Worker                                                 .map_err(der_alloc_err)?)).map_err(der_alloc_err)?;
743*9860b763SAndroid Build Coastguard Worker     };
744*9860b763SAndroid Build Coastguard Worker }
745*9860b763SAndroid Build Coastguard Worker 
decode_value_from_bytes( tag: keymint::Tag, tlv_bytes: &[u8], key_params: &mut Vec<KeyParam>, ) -> Result<(), der::Error>746*9860b763SAndroid Build Coastguard Worker fn decode_value_from_bytes(
747*9860b763SAndroid Build Coastguard Worker     tag: keymint::Tag,
748*9860b763SAndroid Build Coastguard Worker     tlv_bytes: &[u8],
749*9860b763SAndroid Build Coastguard Worker     key_params: &mut Vec<KeyParam>,
750*9860b763SAndroid Build Coastguard Worker ) -> Result<(), der::Error> {
751*9860b763SAndroid Build Coastguard Worker     match tag {
752*9860b763SAndroid Build Coastguard Worker         Tag::Purpose => {
753*9860b763SAndroid Build Coastguard Worker             key_params_from_asn1_set_of_integer!(Purpose, tlv_bytes, key_params);
754*9860b763SAndroid Build Coastguard Worker         }
755*9860b763SAndroid Build Coastguard Worker         Tag::Algorithm => {
756*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(Algorithm, i32, tlv_bytes, key_params);
757*9860b763SAndroid Build Coastguard Worker         }
758*9860b763SAndroid Build Coastguard Worker         Tag::KeySize => {
759*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_newtype!(
760*9860b763SAndroid Build Coastguard Worker                 KeySize,
761*9860b763SAndroid Build Coastguard Worker                 u32,
762*9860b763SAndroid Build Coastguard Worker                 KeySizeInBits,
763*9860b763SAndroid Build Coastguard Worker                 tlv_bytes,
764*9860b763SAndroid Build Coastguard Worker                 key_params
765*9860b763SAndroid Build Coastguard Worker             );
766*9860b763SAndroid Build Coastguard Worker         }
767*9860b763SAndroid Build Coastguard Worker         Tag::BlockMode => {
768*9860b763SAndroid Build Coastguard Worker             key_params_from_asn1_set_of_integer!(BlockMode, tlv_bytes, key_params);
769*9860b763SAndroid Build Coastguard Worker         }
770*9860b763SAndroid Build Coastguard Worker         Tag::Digest => {
771*9860b763SAndroid Build Coastguard Worker             key_params_from_asn1_set_of_integer!(Digest, tlv_bytes, key_params);
772*9860b763SAndroid Build Coastguard Worker         }
773*9860b763SAndroid Build Coastguard Worker         Tag::Padding => {
774*9860b763SAndroid Build Coastguard Worker             key_params_from_asn1_set_of_integer!(Padding, tlv_bytes, key_params);
775*9860b763SAndroid Build Coastguard Worker         }
776*9860b763SAndroid Build Coastguard Worker         Tag::CallerNonce => {
777*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(CallerNonce, tlv_bytes, key_params);
778*9860b763SAndroid Build Coastguard Worker         }
779*9860b763SAndroid Build Coastguard Worker         Tag::MinMacLength => {
780*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(MinMacLength, u32, tlv_bytes, key_params);
781*9860b763SAndroid Build Coastguard Worker         }
782*9860b763SAndroid Build Coastguard Worker         Tag::EcCurve => {
783*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(EcCurve, i32, tlv_bytes, key_params);
784*9860b763SAndroid Build Coastguard Worker         }
785*9860b763SAndroid Build Coastguard Worker         Tag::RsaPublicExponent => {
786*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_newtype!(
787*9860b763SAndroid Build Coastguard Worker                 RsaPublicExponent,
788*9860b763SAndroid Build Coastguard Worker                 u64,
789*9860b763SAndroid Build Coastguard Worker                 RsaExponent,
790*9860b763SAndroid Build Coastguard Worker                 tlv_bytes,
791*9860b763SAndroid Build Coastguard Worker                 key_params
792*9860b763SAndroid Build Coastguard Worker             );
793*9860b763SAndroid Build Coastguard Worker         }
794*9860b763SAndroid Build Coastguard Worker         Tag::RsaOaepMgfDigest => {
795*9860b763SAndroid Build Coastguard Worker             key_params_from_asn1_set_of_integer!(RsaOaepMgfDigest, tlv_bytes, key_params);
796*9860b763SAndroid Build Coastguard Worker         }
797*9860b763SAndroid Build Coastguard Worker         Tag::RollbackResistance => {
798*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(RollbackResistance, tlv_bytes, key_params);
799*9860b763SAndroid Build Coastguard Worker         }
800*9860b763SAndroid Build Coastguard Worker         Tag::EarlyBootOnly => {
801*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(EarlyBootOnly, tlv_bytes, key_params);
802*9860b763SAndroid Build Coastguard Worker         }
803*9860b763SAndroid Build Coastguard Worker         Tag::ActiveDatetime => {
804*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_datetime!(ActiveDatetime, tlv_bytes, key_params);
805*9860b763SAndroid Build Coastguard Worker         }
806*9860b763SAndroid Build Coastguard Worker         Tag::OriginationExpireDatetime => {
807*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_datetime!(OriginationExpireDatetime, tlv_bytes, key_params);
808*9860b763SAndroid Build Coastguard Worker         }
809*9860b763SAndroid Build Coastguard Worker         Tag::UsageExpireDatetime => {
810*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_datetime!(UsageExpireDatetime, tlv_bytes, key_params);
811*9860b763SAndroid Build Coastguard Worker         }
812*9860b763SAndroid Build Coastguard Worker         Tag::UsageCountLimit => {
813*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(UsageCountLimit, u32, tlv_bytes, key_params);
814*9860b763SAndroid Build Coastguard Worker         }
815*9860b763SAndroid Build Coastguard Worker         Tag::UserSecureId => {
816*9860b763SAndroid Build Coastguard Worker             // Note that the `UserSecureId` tag has tag type `ULONG_REP` indicating that it can be
817*9860b763SAndroid Build Coastguard Worker             // repeated, but the ASN.1 schema for `AuthorizationList` has this field as having type
818*9860b763SAndroid Build Coastguard Worker             // `INTEGER` not `SET OF INTEGER`. This reflects the special usage of `UserSecureId`
819*9860b763SAndroid Build Coastguard Worker             // in `importWrappedKey()` processing.
820*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(UserSecureId, u64, tlv_bytes, key_params);
821*9860b763SAndroid Build Coastguard Worker         }
822*9860b763SAndroid Build Coastguard Worker         Tag::NoAuthRequired => {
823*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(NoAuthRequired, tlv_bytes, key_params);
824*9860b763SAndroid Build Coastguard Worker         }
825*9860b763SAndroid Build Coastguard Worker         Tag::UserAuthType => {
826*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(UserAuthType, u32, tlv_bytes, key_params);
827*9860b763SAndroid Build Coastguard Worker         }
828*9860b763SAndroid Build Coastguard Worker         Tag::AuthTimeout => {
829*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(AuthTimeout, u32, tlv_bytes, key_params);
830*9860b763SAndroid Build Coastguard Worker         }
831*9860b763SAndroid Build Coastguard Worker         Tag::AllowWhileOnBody => {
832*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(AllowWhileOnBody, tlv_bytes, key_params);
833*9860b763SAndroid Build Coastguard Worker         }
834*9860b763SAndroid Build Coastguard Worker         Tag::TrustedUserPresenceRequired => {
835*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(TrustedUserPresenceRequired, tlv_bytes, key_params);
836*9860b763SAndroid Build Coastguard Worker         }
837*9860b763SAndroid Build Coastguard Worker         Tag::TrustedConfirmationRequired => {
838*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(TrustedConfirmationRequired, tlv_bytes, key_params);
839*9860b763SAndroid Build Coastguard Worker         }
840*9860b763SAndroid Build Coastguard Worker         Tag::UnlockedDeviceRequired => {
841*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(UnlockedDeviceRequired, tlv_bytes, key_params);
842*9860b763SAndroid Build Coastguard Worker         }
843*9860b763SAndroid Build Coastguard Worker         Tag::CreationDatetime => {
844*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer_datetime!(CreationDatetime, tlv_bytes, key_params);
845*9860b763SAndroid Build Coastguard Worker         }
846*9860b763SAndroid Build Coastguard Worker         Tag::Origin => {
847*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(Origin, i32, tlv_bytes, key_params);
848*9860b763SAndroid Build Coastguard Worker         }
849*9860b763SAndroid Build Coastguard Worker         Tag::RootOfTrust => {
850*9860b763SAndroid Build Coastguard Worker             key_params
851*9860b763SAndroid Build Coastguard Worker                 .try_push(KeyParam::RootOfTrust(try_to_vec(tlv_bytes).map_err(der_alloc_err)?))
852*9860b763SAndroid Build Coastguard Worker                 .map_err(der_alloc_err)?;
853*9860b763SAndroid Build Coastguard Worker         }
854*9860b763SAndroid Build Coastguard Worker         Tag::OsVersion => {
855*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(OsVersion, u32, tlv_bytes, key_params);
856*9860b763SAndroid Build Coastguard Worker         }
857*9860b763SAndroid Build Coastguard Worker         Tag::OsPatchlevel => {
858*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(OsPatchlevel, u32, tlv_bytes, key_params);
859*9860b763SAndroid Build Coastguard Worker         }
860*9860b763SAndroid Build Coastguard Worker         Tag::AttestationApplicationId => {
861*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationApplicationId, tlv_bytes, key_params);
862*9860b763SAndroid Build Coastguard Worker         }
863*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdBrand => {
864*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdBrand, tlv_bytes, key_params);
865*9860b763SAndroid Build Coastguard Worker         }
866*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdDevice => {
867*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdDevice, tlv_bytes, key_params);
868*9860b763SAndroid Build Coastguard Worker         }
869*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdProduct => {
870*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdProduct, tlv_bytes, key_params);
871*9860b763SAndroid Build Coastguard Worker         }
872*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdSerial => {
873*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdSerial, tlv_bytes, key_params);
874*9860b763SAndroid Build Coastguard Worker         }
875*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdImei => {
876*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdImei, tlv_bytes, key_params);
877*9860b763SAndroid Build Coastguard Worker         }
878*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdSecondImei => {
879*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdSecondImei, tlv_bytes, key_params);
880*9860b763SAndroid Build Coastguard Worker         }
881*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdMeid => {
882*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdMeid, tlv_bytes, key_params);
883*9860b763SAndroid Build Coastguard Worker         }
884*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdManufacturer => {
885*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdManufacturer, tlv_bytes, key_params);
886*9860b763SAndroid Build Coastguard Worker         }
887*9860b763SAndroid Build Coastguard Worker         Tag::AttestationIdModel => {
888*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(AttestationIdModel, tlv_bytes, key_params);
889*9860b763SAndroid Build Coastguard Worker         }
890*9860b763SAndroid Build Coastguard Worker         Tag::VendorPatchlevel => {
891*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(VendorPatchlevel, u32, tlv_bytes, key_params);
892*9860b763SAndroid Build Coastguard Worker         }
893*9860b763SAndroid Build Coastguard Worker         Tag::BootPatchlevel => {
894*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_integer!(BootPatchlevel, u32, tlv_bytes, key_params);
895*9860b763SAndroid Build Coastguard Worker         }
896*9860b763SAndroid Build Coastguard Worker         Tag::DeviceUniqueAttestation => {
897*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_null!(DeviceUniqueAttestation, tlv_bytes, key_params);
898*9860b763SAndroid Build Coastguard Worker         }
899*9860b763SAndroid Build Coastguard Worker         Tag::ModuleHash => {
900*9860b763SAndroid Build Coastguard Worker             key_param_from_asn1_octet_string!(ModuleHash, tlv_bytes, key_params);
901*9860b763SAndroid Build Coastguard Worker         }
902*9860b763SAndroid Build Coastguard Worker         _ => {
903*9860b763SAndroid Build Coastguard Worker             // Note: `der::Error` or `der::ErrorKind` is not expressive enough for decoding
904*9860b763SAndroid Build Coastguard Worker             // tags in high tag form. Documentation of this error kind does not match this
905*9860b763SAndroid Build Coastguard Worker             // situation. But we use the `der::ErrorKind` as close as possible.
906*9860b763SAndroid Build Coastguard Worker             return Err(der::ErrorKind::TagNumberInvalid.into());
907*9860b763SAndroid Build Coastguard Worker         }
908*9860b763SAndroid Build Coastguard Worker     }
909*9860b763SAndroid Build Coastguard Worker     Ok(())
910*9860b763SAndroid Build Coastguard Worker }
911*9860b763SAndroid Build Coastguard Worker 
912*9860b763SAndroid Build Coastguard Worker /// Decode the tag of a field in AuthorizationList.
decode_tag_from_bytes<'a, R: der::Reader<'a>>( decoder: &mut R, ) -> Result<Option<keymint::Tag>, der::Error>913*9860b763SAndroid Build Coastguard Worker fn decode_tag_from_bytes<'a, R: der::Reader<'a>>(
914*9860b763SAndroid Build Coastguard Worker     decoder: &mut R,
915*9860b763SAndroid Build Coastguard Worker ) -> Result<Option<keymint::Tag>, der::Error> {
916*9860b763SAndroid Build Coastguard Worker     // Avoid reading for tags beyond the size of the encoded AuthorizationList
917*9860b763SAndroid Build Coastguard Worker     if decoder.remaining_len() == Length::ZERO {
918*9860b763SAndroid Build Coastguard Worker         return Ok(None);
919*9860b763SAndroid Build Coastguard Worker     }
920*9860b763SAndroid Build Coastguard Worker     let b1 = decoder.read_byte()?;
921*9860b763SAndroid Build Coastguard Worker     let raw_tag = if b1 & 0xbfu8 == 0xbfu8 {
922*9860b763SAndroid Build Coastguard Worker         // High tag form, read the next byte
923*9860b763SAndroid Build Coastguard Worker         let b2 = decoder.read_byte()?;
924*9860b763SAndroid Build Coastguard Worker         if b2 & 0x80u8 == 0x80u8 {
925*9860b763SAndroid Build Coastguard Worker             // Encoded tag length is 3, read the next byte
926*9860b763SAndroid Build Coastguard Worker             let b3 = decoder.read_byte()?;
927*9860b763SAndroid Build Coastguard Worker             let tag_byte: u16 = ((b2 ^ 0x80u8) as u16) << 7;
928*9860b763SAndroid Build Coastguard Worker             (tag_byte | b3 as u16) as u32
929*9860b763SAndroid Build Coastguard Worker         } else {
930*9860b763SAndroid Build Coastguard Worker             b2 as u32
931*9860b763SAndroid Build Coastguard Worker         }
932*9860b763SAndroid Build Coastguard Worker     } else {
933*9860b763SAndroid Build Coastguard Worker         (b1 ^ 0b10100000u8) as u32
934*9860b763SAndroid Build Coastguard Worker     };
935*9860b763SAndroid Build Coastguard Worker     let tag = from_raw_tag_value(raw_tag);
936*9860b763SAndroid Build Coastguard Worker     if tag == Tag::Invalid {
937*9860b763SAndroid Build Coastguard Worker         // Note: der::Error or der::ErrorKind is not expressive enough for decoding tags
938*9860b763SAndroid Build Coastguard Worker         // in high tag form. Documentation of this error kind does not match this situation.
939*9860b763SAndroid Build Coastguard Worker         // Find a better way to express the error.
940*9860b763SAndroid Build Coastguard Worker         Err(der::ErrorKind::TagNumberInvalid.into())
941*9860b763SAndroid Build Coastguard Worker     } else {
942*9860b763SAndroid Build Coastguard Worker         Ok(Some(tag))
943*9860b763SAndroid Build Coastguard Worker     }
944*9860b763SAndroid Build Coastguard Worker }
945*9860b763SAndroid Build Coastguard Worker 
946*9860b763SAndroid Build Coastguard Worker // Macros to extract key characteristics for ASN.1 encoding into one of the forms:
947*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT SET OF INTEGER OPTIONAL
948*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT INTEGER OPTIONAL
949*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT NULL OPTIONAL
950*9860b763SAndroid Build Coastguard Worker //   field    [<tag>] EXPLICIT OCTET STRING OPTIONAL
951*9860b763SAndroid Build Coastguard Worker // together with an extra variant that deals with OCTET STRING values that must match
952*9860b763SAndroid Build Coastguard Worker // a provisioned attestation ID value.
953*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_set_of_integer {
954*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
955*9860b763SAndroid Build Coastguard Worker         {
956*9860b763SAndroid Build Coastguard Worker             let mut results = Vec::new();
957*9860b763SAndroid Build Coastguard Worker             for param in $params.as_ref() {
958*9860b763SAndroid Build Coastguard Worker                 if let KeyParam::$variant(v) = param {
959*9860b763SAndroid Build Coastguard Worker                     results.try_push(v.clone()).map_err(der_alloc_err)?;
960*9860b763SAndroid Build Coastguard Worker                 }
961*9860b763SAndroid Build Coastguard Worker             }
962*9860b763SAndroid Build Coastguard Worker             if !results.is_empty() {
963*9860b763SAndroid Build Coastguard Worker                 // The input key characteristics have been sorted and so are in numerical order, but
964*9860b763SAndroid Build Coastguard Worker                 // may contain duplicates that need to be weeded out.
965*9860b763SAndroid Build Coastguard Worker                 let mut set = der::asn1::SetOfVec::new();
966*9860b763SAndroid Build Coastguard Worker                 let mut prev_val = None;
967*9860b763SAndroid Build Coastguard Worker                 for val in results {
968*9860b763SAndroid Build Coastguard Worker                     let val = val as i64;
969*9860b763SAndroid Build Coastguard Worker                     if let Some(prev) = prev_val {
970*9860b763SAndroid Build Coastguard Worker                         if prev == val {
971*9860b763SAndroid Build Coastguard Worker                             continue; // skip duplicate
972*9860b763SAndroid Build Coastguard Worker                         }
973*9860b763SAndroid Build Coastguard Worker                     }
974*9860b763SAndroid Build Coastguard Worker                     set.insert_ordered(val)?;
975*9860b763SAndroid Build Coastguard Worker                     prev_val = Some(val);
976*9860b763SAndroid Build Coastguard Worker                 }
977*9860b763SAndroid Build Coastguard Worker                 Some(ExplicitTaggedValue {
978*9860b763SAndroid Build Coastguard Worker                     tag: raw_tag_value(Tag::$variant),
979*9860b763SAndroid Build Coastguard Worker                     val: set,
980*9860b763SAndroid Build Coastguard Worker                 })
981*9860b763SAndroid Build Coastguard Worker             } else {
982*9860b763SAndroid Build Coastguard Worker                 None
983*9860b763SAndroid Build Coastguard Worker             }
984*9860b763SAndroid Build Coastguard Worker         }
985*9860b763SAndroid Build Coastguard Worker     }
986*9860b763SAndroid Build Coastguard Worker }
987*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_integer {
988*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
989*9860b763SAndroid Build Coastguard Worker         if let Some(val) = get_opt_tag_value!($params.as_ref(), $variant).map_err(|_e| {
990*9860b763SAndroid Build Coastguard Worker             log::warn!("failed to get {} value for ext", stringify!($variant));
991*9860b763SAndroid Build Coastguard Worker             der::Error::new(der::ErrorKind::Failed, der::Length::ZERO)
992*9860b763SAndroid Build Coastguard Worker         })? {
993*9860b763SAndroid Build Coastguard Worker             Some(ExplicitTaggedValue {
994*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::$variant),
995*9860b763SAndroid Build Coastguard Worker                 val: *val as i64
996*9860b763SAndroid Build Coastguard Worker             })
997*9860b763SAndroid Build Coastguard Worker         } else {
998*9860b763SAndroid Build Coastguard Worker             None
999*9860b763SAndroid Build Coastguard Worker         }
1000*9860b763SAndroid Build Coastguard Worker     }
1001*9860b763SAndroid Build Coastguard Worker }
1002*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_integer_newtype {
1003*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
1004*9860b763SAndroid Build Coastguard Worker         if let Some(val) = get_opt_tag_value!($params.as_ref(), $variant).map_err(|_e| {
1005*9860b763SAndroid Build Coastguard Worker             log::warn!("failed to get {} value for ext", stringify!($variant));
1006*9860b763SAndroid Build Coastguard Worker             der::Error::new(der::ErrorKind::Failed, der::Length::ZERO)
1007*9860b763SAndroid Build Coastguard Worker         })? {
1008*9860b763SAndroid Build Coastguard Worker             Some(ExplicitTaggedValue {
1009*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::$variant),
1010*9860b763SAndroid Build Coastguard Worker                 val: val.0 as i64
1011*9860b763SAndroid Build Coastguard Worker             })
1012*9860b763SAndroid Build Coastguard Worker         } else {
1013*9860b763SAndroid Build Coastguard Worker             None
1014*9860b763SAndroid Build Coastguard Worker         }
1015*9860b763SAndroid Build Coastguard Worker     }
1016*9860b763SAndroid Build Coastguard Worker }
1017*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_integer_datetime {
1018*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
1019*9860b763SAndroid Build Coastguard Worker         if let Some(val) = get_opt_tag_value!($params.as_ref(), $variant).map_err(|_e| {
1020*9860b763SAndroid Build Coastguard Worker             log::warn!("failed to get {} value for ext", stringify!($variant));
1021*9860b763SAndroid Build Coastguard Worker             der::Error::new(der::ErrorKind::Failed, der::Length::ZERO)
1022*9860b763SAndroid Build Coastguard Worker         })? {
1023*9860b763SAndroid Build Coastguard Worker             Some(ExplicitTaggedValue {
1024*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::$variant),
1025*9860b763SAndroid Build Coastguard Worker                 val: val.ms_since_epoch
1026*9860b763SAndroid Build Coastguard Worker             })
1027*9860b763SAndroid Build Coastguard Worker         } else {
1028*9860b763SAndroid Build Coastguard Worker             None
1029*9860b763SAndroid Build Coastguard Worker         }
1030*9860b763SAndroid Build Coastguard Worker     }
1031*9860b763SAndroid Build Coastguard Worker }
1032*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_null {
1033*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
1034*9860b763SAndroid Build Coastguard Worker         if get_bool_tag_value!($params.as_ref(), $variant).map_err(|_e| {
1035*9860b763SAndroid Build Coastguard Worker             log::warn!("failed to get {} value for ext", stringify!($variant));
1036*9860b763SAndroid Build Coastguard Worker             der::Error::new(der::ErrorKind::Failed, der::Length::ZERO)
1037*9860b763SAndroid Build Coastguard Worker         })? {
1038*9860b763SAndroid Build Coastguard Worker             Some(ExplicitTaggedValue {
1039*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::$variant),
1040*9860b763SAndroid Build Coastguard Worker                 val: ()
1041*9860b763SAndroid Build Coastguard Worker             })
1042*9860b763SAndroid Build Coastguard Worker         } else {
1043*9860b763SAndroid Build Coastguard Worker             None
1044*9860b763SAndroid Build Coastguard Worker         }
1045*9860b763SAndroid Build Coastguard Worker     }
1046*9860b763SAndroid Build Coastguard Worker }
1047*9860b763SAndroid Build Coastguard Worker macro_rules! asn1_octet_string {
1048*9860b763SAndroid Build Coastguard Worker     { $params:expr, $variant:ident } => {
1049*9860b763SAndroid Build Coastguard Worker         if let Some(val) = get_opt_tag_value!($params.as_ref(), $variant).map_err(|_e| {
1050*9860b763SAndroid Build Coastguard Worker             log::warn!("failed to get {} value for ext", stringify!($variant));
1051*9860b763SAndroid Build Coastguard Worker             der::Error::new(der::ErrorKind::Failed, der::Length::ZERO)
1052*9860b763SAndroid Build Coastguard Worker         })? {
1053*9860b763SAndroid Build Coastguard Worker             Some(ExplicitTaggedValue {
1054*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::$variant),
1055*9860b763SAndroid Build Coastguard Worker                 val: der::asn1::OctetStringRef::new(val)?,
1056*9860b763SAndroid Build Coastguard Worker             })
1057*9860b763SAndroid Build Coastguard Worker         } else {
1058*9860b763SAndroid Build Coastguard Worker             None
1059*9860b763SAndroid Build Coastguard Worker         }
1060*9860b763SAndroid Build Coastguard Worker     }
1061*9860b763SAndroid Build Coastguard Worker }
1062*9860b763SAndroid Build Coastguard Worker 
asn1_val<T: Encode>( val: Option<ExplicitTaggedValue<T>>, writer: &mut impl der::Writer, ) -> der::Result<()>1063*9860b763SAndroid Build Coastguard Worker fn asn1_val<T: Encode>(
1064*9860b763SAndroid Build Coastguard Worker     val: Option<ExplicitTaggedValue<T>>,
1065*9860b763SAndroid Build Coastguard Worker     writer: &mut impl der::Writer,
1066*9860b763SAndroid Build Coastguard Worker ) -> der::Result<()> {
1067*9860b763SAndroid Build Coastguard Worker     if let Some(val) = val {
1068*9860b763SAndroid Build Coastguard Worker         val.encode(writer)
1069*9860b763SAndroid Build Coastguard Worker     } else {
1070*9860b763SAndroid Build Coastguard Worker         Ok(())
1071*9860b763SAndroid Build Coastguard Worker     }
1072*9860b763SAndroid Build Coastguard Worker }
1073*9860b763SAndroid Build Coastguard Worker 
asn1_len<T: Encode>(val: Option<ExplicitTaggedValue<T>>) -> der::Result<Length>1074*9860b763SAndroid Build Coastguard Worker fn asn1_len<T: Encode>(val: Option<ExplicitTaggedValue<T>>) -> der::Result<Length> {
1075*9860b763SAndroid Build Coastguard Worker     match val {
1076*9860b763SAndroid Build Coastguard Worker         Some(val) => val.encoded_len(),
1077*9860b763SAndroid Build Coastguard Worker         None => Ok(Length::ZERO),
1078*9860b763SAndroid Build Coastguard Worker     }
1079*9860b763SAndroid Build Coastguard Worker }
1080*9860b763SAndroid Build Coastguard Worker 
1081*9860b763SAndroid Build Coastguard Worker impl<'a> Sequence<'a> for AuthorizationList<'a> {}
1082*9860b763SAndroid Build Coastguard Worker 
1083*9860b763SAndroid Build Coastguard Worker impl<'a> EncodeValue for AuthorizationList<'a> {
value_len(&self) -> der::Result<Length>1084*9860b763SAndroid Build Coastguard Worker     fn value_len(&self) -> der::Result<Length> {
1085*9860b763SAndroid Build Coastguard Worker         let mut length = asn1_len(asn1_set_of_integer!(self.auths, Purpose))?
1086*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, Algorithm))?
1087*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_newtype!(self.auths, KeySize))?
1088*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_set_of_integer!(self.auths, BlockMode))?
1089*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_set_of_integer!(self.auths, Digest))?
1090*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_set_of_integer!(self.auths, Padding))?
1091*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, CallerNonce))?
1092*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, MinMacLength))?
1093*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, EcCurve))?
1094*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_newtype!(self.auths, RsaPublicExponent))?
1095*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_set_of_integer!(self.auths, RsaOaepMgfDigest))?
1096*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, RollbackResistance))?
1097*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, EarlyBootOnly))?
1098*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_datetime!(self.auths, ActiveDatetime))?
1099*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_datetime!(self.auths, OriginationExpireDatetime))?
1100*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_datetime!(self.auths, UsageExpireDatetime))?
1101*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, UsageCountLimit))?
1102*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, NoAuthRequired))?
1103*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, UserAuthType))?
1104*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, AuthTimeout))?
1105*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, AllowWhileOnBody))?
1106*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, TrustedUserPresenceRequired))?
1107*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, TrustedConfirmationRequired))?
1108*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, UnlockedDeviceRequired))?
1109*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer_datetime!(self.auths, CreationDatetime))?
1110*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, Origin))?;
1111*9860b763SAndroid Build Coastguard Worker         if let Some(KeyParam::RootOfTrust(encoded_rot_info)) = &self.rot_info {
1112*9860b763SAndroid Build Coastguard Worker             length = length
1113*9860b763SAndroid Build Coastguard Worker                 + ExplicitTaggedValue {
1114*9860b763SAndroid Build Coastguard Worker                     tag: raw_tag_value(Tag::RootOfTrust),
1115*9860b763SAndroid Build Coastguard Worker                     val: RootOfTrust::from_der(encoded_rot_info.as_slice())?,
1116*9860b763SAndroid Build Coastguard Worker                 }
1117*9860b763SAndroid Build Coastguard Worker                 .encoded_len()?;
1118*9860b763SAndroid Build Coastguard Worker         }
1119*9860b763SAndroid Build Coastguard Worker         length = length
1120*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, OsVersion))?
1121*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, OsPatchlevel))?;
1122*9860b763SAndroid Build Coastguard Worker         if let Some(KeyParam::AttestationApplicationId(app_id)) = &self.app_id {
1123*9860b763SAndroid Build Coastguard Worker             length = length
1124*9860b763SAndroid Build Coastguard Worker                 + ExplicitTaggedValue {
1125*9860b763SAndroid Build Coastguard Worker                     tag: raw_tag_value(Tag::AttestationApplicationId),
1126*9860b763SAndroid Build Coastguard Worker                     val: der::asn1::OctetStringRef::new(app_id.as_slice())?,
1127*9860b763SAndroid Build Coastguard Worker                 }
1128*9860b763SAndroid Build Coastguard Worker                 .encoded_len()?;
1129*9860b763SAndroid Build Coastguard Worker         }
1130*9860b763SAndroid Build Coastguard Worker         length = length
1131*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdBrand))?
1132*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdDevice))?
1133*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdProduct))?
1134*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdSerial))?
1135*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdImei))?
1136*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdMeid))?
1137*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdManufacturer))?
1138*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdModel))?
1139*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, VendorPatchlevel))?
1140*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_integer!(self.auths, BootPatchlevel))?
1141*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_null!(self.auths, DeviceUniqueAttestation))?
1142*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.keygen_params, AttestationIdSecondImei))?
1143*9860b763SAndroid Build Coastguard Worker             + asn1_len(asn1_octet_string!(&self.additional_attestation_info, ModuleHash))?;
1144*9860b763SAndroid Build Coastguard Worker         length
1145*9860b763SAndroid Build Coastguard Worker     }
1146*9860b763SAndroid Build Coastguard Worker 
encode_value(&self, writer: &mut impl der::Writer) -> der::Result<()>1147*9860b763SAndroid Build Coastguard Worker     fn encode_value(&self, writer: &mut impl der::Writer) -> der::Result<()> {
1148*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_set_of_integer!(self.auths, Purpose), writer)?;
1149*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, Algorithm), writer)?;
1150*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_newtype!(self.auths, KeySize), writer)?;
1151*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_set_of_integer!(self.auths, BlockMode), writer)?;
1152*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_set_of_integer!(self.auths, Digest), writer)?;
1153*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_set_of_integer!(self.auths, Padding), writer)?;
1154*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, CallerNonce), writer)?;
1155*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, MinMacLength), writer)?;
1156*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, EcCurve), writer)?;
1157*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_newtype!(self.auths, RsaPublicExponent), writer)?;
1158*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_set_of_integer!(self.auths, RsaOaepMgfDigest), writer)?;
1159*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, RollbackResistance), writer)?;
1160*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, EarlyBootOnly), writer)?;
1161*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_datetime!(self.auths, ActiveDatetime), writer)?;
1162*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_datetime!(self.auths, OriginationExpireDatetime), writer)?;
1163*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_datetime!(self.auths, UsageExpireDatetime), writer)?;
1164*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, UsageCountLimit), writer)?;
1165*9860b763SAndroid Build Coastguard Worker         // Skip `UserSecureId` as it's only included in the extension for
1166*9860b763SAndroid Build Coastguard Worker         // importWrappedKey() cases.
1167*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, NoAuthRequired), writer)?;
1168*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, UserAuthType), writer)?;
1169*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, AuthTimeout), writer)?;
1170*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, AllowWhileOnBody), writer)?;
1171*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, TrustedUserPresenceRequired), writer)?;
1172*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, TrustedConfirmationRequired), writer)?;
1173*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, UnlockedDeviceRequired), writer)?;
1174*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer_datetime!(self.auths, CreationDatetime), writer)?;
1175*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, Origin), writer)?;
1176*9860b763SAndroid Build Coastguard Worker         // Root of trust info is a special case (not in key characteristics).
1177*9860b763SAndroid Build Coastguard Worker         if let Some(KeyParam::RootOfTrust(encoded_rot_info)) = &self.rot_info {
1178*9860b763SAndroid Build Coastguard Worker             ExplicitTaggedValue {
1179*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::RootOfTrust),
1180*9860b763SAndroid Build Coastguard Worker                 val: RootOfTrust::from_der(encoded_rot_info.as_slice())?,
1181*9860b763SAndroid Build Coastguard Worker             }
1182*9860b763SAndroid Build Coastguard Worker             .encode(writer)?;
1183*9860b763SAndroid Build Coastguard Worker         }
1184*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, OsVersion), writer)?;
1185*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, OsPatchlevel), writer)?;
1186*9860b763SAndroid Build Coastguard Worker         // Attestation application ID is a special case (not in key characteristics).
1187*9860b763SAndroid Build Coastguard Worker         if let Some(KeyParam::AttestationApplicationId(app_id)) = &self.app_id {
1188*9860b763SAndroid Build Coastguard Worker             ExplicitTaggedValue {
1189*9860b763SAndroid Build Coastguard Worker                 tag: raw_tag_value(Tag::AttestationApplicationId),
1190*9860b763SAndroid Build Coastguard Worker                 val: der::asn1::OctetStringRef::new(app_id.as_slice())?,
1191*9860b763SAndroid Build Coastguard Worker             }
1192*9860b763SAndroid Build Coastguard Worker             .encode(writer)?;
1193*9860b763SAndroid Build Coastguard Worker         }
1194*9860b763SAndroid Build Coastguard Worker         // Accuracy of attestation IDs has already been checked, so just copy across.
1195*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdBrand), writer)?;
1196*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdDevice), writer)?;
1197*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdProduct), writer)?;
1198*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdSerial), writer)?;
1199*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdImei), writer)?;
1200*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdMeid), writer)?;
1201*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdManufacturer), writer)?;
1202*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdModel), writer)?;
1203*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, VendorPatchlevel), writer)?;
1204*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_integer!(self.auths, BootPatchlevel), writer)?;
1205*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_null!(self.auths, DeviceUniqueAttestation), writer)?;
1206*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.keygen_params, AttestationIdSecondImei), writer)?;
1207*9860b763SAndroid Build Coastguard Worker         asn1_val(asn1_octet_string!(&self.additional_attestation_info, ModuleHash), writer)?;
1208*9860b763SAndroid Build Coastguard Worker         Ok(())
1209*9860b763SAndroid Build Coastguard Worker     }
1210*9860b763SAndroid Build Coastguard Worker }
1211*9860b763SAndroid Build Coastguard Worker 
1212*9860b763SAndroid Build Coastguard Worker struct ExplicitTaggedValue<T: Encode> {
1213*9860b763SAndroid Build Coastguard Worker     pub tag: u32,
1214*9860b763SAndroid Build Coastguard Worker     pub val: T,
1215*9860b763SAndroid Build Coastguard Worker }
1216*9860b763SAndroid Build Coastguard Worker 
1217*9860b763SAndroid Build Coastguard Worker impl<T: Encode> ExplicitTaggedValue<T> {
explicit_tag_len(&self) -> der::Result<der::Length>1218*9860b763SAndroid Build Coastguard Worker     fn explicit_tag_len(&self) -> der::Result<der::Length> {
1219*9860b763SAndroid Build Coastguard Worker         match self.tag {
1220*9860b763SAndroid Build Coastguard Worker             0..=0x1e => Ok(der::Length::ONE),
1221*9860b763SAndroid Build Coastguard Worker             0x1f..=0x7f => Ok(der::Length::new(2)),
1222*9860b763SAndroid Build Coastguard Worker             0x80..=0x3fff => Ok(der::Length::new(3)),
1223*9860b763SAndroid Build Coastguard Worker             _ => Err(der::ErrorKind::Overflow.into()),
1224*9860b763SAndroid Build Coastguard Worker         }
1225*9860b763SAndroid Build Coastguard Worker     }
1226*9860b763SAndroid Build Coastguard Worker 
explicit_tag_encode(&self, encoder: &mut dyn der::Writer) -> der::Result<()>1227*9860b763SAndroid Build Coastguard Worker     fn explicit_tag_encode(&self, encoder: &mut dyn der::Writer) -> der::Result<()> {
1228*9860b763SAndroid Build Coastguard Worker         match self.tag {
1229*9860b763SAndroid Build Coastguard Worker             0..=0x1e => {
1230*9860b763SAndroid Build Coastguard Worker                 // b101vvvvv is context-specific+constructed
1231*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte(0b10100000u8 | (self.tag as u8))
1232*9860b763SAndroid Build Coastguard Worker             }
1233*9860b763SAndroid Build Coastguard Worker             0x1f..=0x7f => {
1234*9860b763SAndroid Build Coastguard Worker                 // b101 11111 indicates a context-specific+constructed long-form tag number
1235*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte(0b10111111)?;
1236*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte(self.tag as u8)
1237*9860b763SAndroid Build Coastguard Worker             }
1238*9860b763SAndroid Build Coastguard Worker             0x80..=0x3fff => {
1239*9860b763SAndroid Build Coastguard Worker                 // b101 11111 indicates a context-specific+constructed long-form tag number
1240*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte(0b10111111)?;
1241*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte((self.tag >> 7) as u8 | 0x80u8)?;
1242*9860b763SAndroid Build Coastguard Worker                 encoder.write_byte((self.tag & 0x007f) as u8)
1243*9860b763SAndroid Build Coastguard Worker             }
1244*9860b763SAndroid Build Coastguard Worker             _ => Err(der::ErrorKind::Overflow.into()),
1245*9860b763SAndroid Build Coastguard Worker         }
1246*9860b763SAndroid Build Coastguard Worker     }
1247*9860b763SAndroid Build Coastguard Worker }
1248*9860b763SAndroid Build Coastguard Worker 
1249*9860b763SAndroid Build Coastguard Worker /// The der library explicitly does not support `TagNumber` values bigger than 31,
1250*9860b763SAndroid Build Coastguard Worker /// which are required here.  Work around this by manually providing the encoding functionality.
1251*9860b763SAndroid Build Coastguard Worker impl<T: Encode> Encode for ExplicitTaggedValue<T> {
encoded_len(&self) -> der::Result<der::Length>1252*9860b763SAndroid Build Coastguard Worker     fn encoded_len(&self) -> der::Result<der::Length> {
1253*9860b763SAndroid Build Coastguard Worker         let inner_len = self.val.encoded_len()?;
1254*9860b763SAndroid Build Coastguard Worker         self.explicit_tag_len() + inner_len.encoded_len()? + inner_len
1255*9860b763SAndroid Build Coastguard Worker     }
1256*9860b763SAndroid Build Coastguard Worker 
encode(&self, encoder: &mut impl der::Writer) -> der::Result<()>1257*9860b763SAndroid Build Coastguard Worker     fn encode(&self, encoder: &mut impl der::Writer) -> der::Result<()> {
1258*9860b763SAndroid Build Coastguard Worker         let inner_len = self.val.encoded_len()?;
1259*9860b763SAndroid Build Coastguard Worker         self.explicit_tag_encode(encoder)?;
1260*9860b763SAndroid Build Coastguard Worker         inner_len.encode(encoder)?;
1261*9860b763SAndroid Build Coastguard Worker         self.val.encode(encoder)
1262*9860b763SAndroid Build Coastguard Worker     }
1263*9860b763SAndroid Build Coastguard Worker }
1264*9860b763SAndroid Build Coastguard Worker 
1265*9860b763SAndroid Build Coastguard Worker /// Root of Trust ASN.1 structure
1266*9860b763SAndroid Build Coastguard Worker /// ```asn1
1267*9860b763SAndroid Build Coastguard Worker ///  * RootOfTrust ::= SEQUENCE {
1268*9860b763SAndroid Build Coastguard Worker ///  *     verifiedBootKey            OCTET_STRING,
1269*9860b763SAndroid Build Coastguard Worker ///  *     deviceLocked               BOOLEAN,
1270*9860b763SAndroid Build Coastguard Worker ///  *     verifiedBootState          VerifiedBootState,
1271*9860b763SAndroid Build Coastguard Worker ///  *     verifiedBootHash           OCTET_STRING,
1272*9860b763SAndroid Build Coastguard Worker ///  * }
1273*9860b763SAndroid Build Coastguard Worker /// ```
1274*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Sequence)]
1275*9860b763SAndroid Build Coastguard Worker struct RootOfTrust<'a> {
1276*9860b763SAndroid Build Coastguard Worker     #[asn1(type = "OCTET STRING")]
1277*9860b763SAndroid Build Coastguard Worker     verified_boot_key: &'a [u8],
1278*9860b763SAndroid Build Coastguard Worker     device_locked: bool,
1279*9860b763SAndroid Build Coastguard Worker     verified_boot_state: VerifiedBootState,
1280*9860b763SAndroid Build Coastguard Worker     #[asn1(type = "OCTET STRING")]
1281*9860b763SAndroid Build Coastguard Worker     verified_boot_hash: &'a [u8],
1282*9860b763SAndroid Build Coastguard Worker }
1283*9860b763SAndroid Build Coastguard Worker 
1284*9860b763SAndroid Build Coastguard Worker impl<'a> From<&'a keymint::BootInfo> for RootOfTrust<'a> {
from(info: &keymint::BootInfo) -> RootOfTrust1285*9860b763SAndroid Build Coastguard Worker     fn from(info: &keymint::BootInfo) -> RootOfTrust {
1286*9860b763SAndroid Build Coastguard Worker         let verified_boot_key: &[u8] = if info.verified_boot_key.is_empty() {
1287*9860b763SAndroid Build Coastguard Worker             // If an empty verified boot key was passed by the boot loader, set the verified boot
1288*9860b763SAndroid Build Coastguard Worker             // key in the attestation to all zeroes.
1289*9860b763SAndroid Build Coastguard Worker             &EMPTY_BOOT_KEY[..]
1290*9860b763SAndroid Build Coastguard Worker         } else {
1291*9860b763SAndroid Build Coastguard Worker             &info.verified_boot_key[..]
1292*9860b763SAndroid Build Coastguard Worker         };
1293*9860b763SAndroid Build Coastguard Worker         RootOfTrust {
1294*9860b763SAndroid Build Coastguard Worker             verified_boot_key,
1295*9860b763SAndroid Build Coastguard Worker             device_locked: info.device_boot_locked,
1296*9860b763SAndroid Build Coastguard Worker             verified_boot_state: info.verified_boot_state.into(),
1297*9860b763SAndroid Build Coastguard Worker             verified_boot_hash: &info.verified_boot_hash[..],
1298*9860b763SAndroid Build Coastguard Worker         }
1299*9860b763SAndroid Build Coastguard Worker     }
1300*9860b763SAndroid Build Coastguard Worker }
1301*9860b763SAndroid Build Coastguard Worker 
1302*9860b763SAndroid Build Coastguard Worker /// Verified Boot State as ASN.1 ENUMERATED type.
1303*9860b763SAndroid Build Coastguard Worker ///```asn1
1304*9860b763SAndroid Build Coastguard Worker ///  * VerifiedBootState ::= ENUMERATED {
1305*9860b763SAndroid Build Coastguard Worker ///  *     Verified                   (0),
1306*9860b763SAndroid Build Coastguard Worker ///  *     SelfSigned                 (1),
1307*9860b763SAndroid Build Coastguard Worker ///  *     Unverified                 (2),
1308*9860b763SAndroid Build Coastguard Worker ///  *     Failed                     (3),
1309*9860b763SAndroid Build Coastguard Worker ///  * }
1310*9860b763SAndroid Build Coastguard Worker ///```
1311*9860b763SAndroid Build Coastguard Worker #[repr(u32)]
1312*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Enumerated)]
1313*9860b763SAndroid Build Coastguard Worker enum VerifiedBootState {
1314*9860b763SAndroid Build Coastguard Worker     Verified = 0,
1315*9860b763SAndroid Build Coastguard Worker     SelfSigned = 1,
1316*9860b763SAndroid Build Coastguard Worker     Unverified = 2,
1317*9860b763SAndroid Build Coastguard Worker     Failed = 3,
1318*9860b763SAndroid Build Coastguard Worker }
1319*9860b763SAndroid Build Coastguard Worker 
1320*9860b763SAndroid Build Coastguard Worker impl From<keymint::VerifiedBootState> for VerifiedBootState {
from(state: keymint::VerifiedBootState) -> VerifiedBootState1321*9860b763SAndroid Build Coastguard Worker     fn from(state: keymint::VerifiedBootState) -> VerifiedBootState {
1322*9860b763SAndroid Build Coastguard Worker         match state {
1323*9860b763SAndroid Build Coastguard Worker             keymint::VerifiedBootState::Verified => VerifiedBootState::Verified,
1324*9860b763SAndroid Build Coastguard Worker             keymint::VerifiedBootState::SelfSigned => VerifiedBootState::SelfSigned,
1325*9860b763SAndroid Build Coastguard Worker             keymint::VerifiedBootState::Unverified => VerifiedBootState::Unverified,
1326*9860b763SAndroid Build Coastguard Worker             keymint::VerifiedBootState::Failed => VerifiedBootState::Failed,
1327*9860b763SAndroid Build Coastguard Worker         }
1328*9860b763SAndroid Build Coastguard Worker     }
1329*9860b763SAndroid Build Coastguard Worker }
1330*9860b763SAndroid Build Coastguard Worker 
1331*9860b763SAndroid Build Coastguard Worker #[cfg(test)]
1332*9860b763SAndroid Build Coastguard Worker mod tests {
1333*9860b763SAndroid Build Coastguard Worker     use super::*;
1334*9860b763SAndroid Build Coastguard Worker     use crate::KeyMintHalVersion;
1335*9860b763SAndroid Build Coastguard Worker     use alloc::vec;
1336*9860b763SAndroid Build Coastguard Worker 
1337*9860b763SAndroid Build Coastguard Worker     #[test]
test_attest_ext_encode_decode()1338*9860b763SAndroid Build Coastguard Worker     fn test_attest_ext_encode_decode() {
1339*9860b763SAndroid Build Coastguard Worker         let sec_level = SecurityLevel::TrustedEnvironment;
1340*9860b763SAndroid Build Coastguard Worker         let ext = AttestationExtension {
1341*9860b763SAndroid Build Coastguard Worker             attestation_version: KeyMintHalVersion::V3 as i32,
1342*9860b763SAndroid Build Coastguard Worker             attestation_security_level: sec_level,
1343*9860b763SAndroid Build Coastguard Worker             keymint_version: KeyMintHalVersion::V3 as i32,
1344*9860b763SAndroid Build Coastguard Worker             keymint_security_level: sec_level,
1345*9860b763SAndroid Build Coastguard Worker             attestation_challenge: b"abc",
1346*9860b763SAndroid Build Coastguard Worker             unique_id: b"xxx",
1347*9860b763SAndroid Build Coastguard Worker             sw_enforced: AuthorizationList::new(&[], &[], None, None, None, &[]).unwrap(),
1348*9860b763SAndroid Build Coastguard Worker             hw_enforced: AuthorizationList::new(
1349*9860b763SAndroid Build Coastguard Worker                 &[KeyParam::Algorithm(keymint::Algorithm::Ec)],
1350*9860b763SAndroid Build Coastguard Worker                 &[],
1351*9860b763SAndroid Build Coastguard Worker                 None,
1352*9860b763SAndroid Build Coastguard Worker                 Some(RootOfTrust {
1353*9860b763SAndroid Build Coastguard Worker                     verified_boot_key: &[0xbbu8; 32],
1354*9860b763SAndroid Build Coastguard Worker                     device_locked: false,
1355*9860b763SAndroid Build Coastguard Worker                     verified_boot_state: VerifiedBootState::Unverified,
1356*9860b763SAndroid Build Coastguard Worker                     verified_boot_hash: &[0xee; 32],
1357*9860b763SAndroid Build Coastguard Worker                 }),
1358*9860b763SAndroid Build Coastguard Worker                 None,
1359*9860b763SAndroid Build Coastguard Worker                 &[],
1360*9860b763SAndroid Build Coastguard Worker             )
1361*9860b763SAndroid Build Coastguard Worker             .unwrap(),
1362*9860b763SAndroid Build Coastguard Worker         };
1363*9860b763SAndroid Build Coastguard Worker         let got = ext.to_der().unwrap();
1364*9860b763SAndroid Build Coastguard Worker         let want = concat!(
1365*9860b763SAndroid Build Coastguard Worker             "3071",   // SEQUENCE
1366*9860b763SAndroid Build Coastguard Worker             "0202",   // INTEGER len 2
1367*9860b763SAndroid Build Coastguard Worker             "012c",   // 300
1368*9860b763SAndroid Build Coastguard Worker             "0a01",   // ENUM len 1
1369*9860b763SAndroid Build Coastguard Worker             "01",     // 1 (TrustedEnvironment)
1370*9860b763SAndroid Build Coastguard Worker             "0202",   // INTEGER len 2
1371*9860b763SAndroid Build Coastguard Worker             "012c",   // 300
1372*9860b763SAndroid Build Coastguard Worker             "0a01",   // ENUM len 1
1373*9860b763SAndroid Build Coastguard Worker             "01",     // 1 (TrustedEnvironement)
1374*9860b763SAndroid Build Coastguard Worker             "0403",   // BYTE STRING len 3
1375*9860b763SAndroid Build Coastguard Worker             "616263", // b"abc"
1376*9860b763SAndroid Build Coastguard Worker             "0403",   // BYTE STRING len 3
1377*9860b763SAndroid Build Coastguard Worker             "787878", // b"xxx"
1378*9860b763SAndroid Build Coastguard Worker             "3000",   // SEQUENCE len 0
1379*9860b763SAndroid Build Coastguard Worker             "3055",   // SEQUENCE len 55
1380*9860b763SAndroid Build Coastguard Worker             "a203",   // EXPLICIT [2]
1381*9860b763SAndroid Build Coastguard Worker             "0201",   // INTEGER len 1
1382*9860b763SAndroid Build Coastguard Worker             "03",     // 3 (Algorithm::Ec)
1383*9860b763SAndroid Build Coastguard Worker             "bf8540",
1384*9860b763SAndroid Build Coastguard Worker             "4c",   // EXPLICIT [704] len 0x4c
1385*9860b763SAndroid Build Coastguard Worker             "304a", // SEQUENCE len x4a
1386*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1387*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1388*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1389*9860b763SAndroid Build Coastguard Worker             "0101", // BOOLEAN len 1
1390*9860b763SAndroid Build Coastguard Worker             "00",   // false
1391*9860b763SAndroid Build Coastguard Worker             "0a01", // ENUMERATED len 1
1392*9860b763SAndroid Build Coastguard Worker             "02",   // Unverified(2)
1393*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1394*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1395*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1396*9860b763SAndroid Build Coastguard Worker         );
1397*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(&got), want);
1398*9860b763SAndroid Build Coastguard Worker         assert_eq!(AttestationExtension::from_der(&got).unwrap(), ext);
1399*9860b763SAndroid Build Coastguard Worker     }
1400*9860b763SAndroid Build Coastguard Worker 
1401*9860b763SAndroid Build Coastguard Worker     #[test]
test_explicit_tagged_value()1402*9860b763SAndroid Build Coastguard Worker     fn test_explicit_tagged_value() {
1403*9860b763SAndroid Build Coastguard Worker         assert_eq!(
1404*9860b763SAndroid Build Coastguard Worker             hex::encode(ExplicitTaggedValue { tag: 2, val: 16 }.to_der().unwrap()),
1405*9860b763SAndroid Build Coastguard Worker             "a203020110"
1406*9860b763SAndroid Build Coastguard Worker         );
1407*9860b763SAndroid Build Coastguard Worker         assert_eq!(
1408*9860b763SAndroid Build Coastguard Worker             hex::encode(ExplicitTaggedValue { tag: 2, val: () }.to_der().unwrap()),
1409*9860b763SAndroid Build Coastguard Worker             "a2020500"
1410*9860b763SAndroid Build Coastguard Worker         );
1411*9860b763SAndroid Build Coastguard Worker         assert_eq!(
1412*9860b763SAndroid Build Coastguard Worker             hex::encode(ExplicitTaggedValue { tag: 503, val: 16 }.to_der().unwrap()),
1413*9860b763SAndroid Build Coastguard Worker             "bf837703020110"
1414*9860b763SAndroid Build Coastguard Worker         );
1415*9860b763SAndroid Build Coastguard Worker     }
1416*9860b763SAndroid Build Coastguard Worker 
1417*9860b763SAndroid Build Coastguard Worker     #[test]
test_authz_list_encode_decode()1418*9860b763SAndroid Build Coastguard Worker     fn test_authz_list_encode_decode() {
1419*9860b763SAndroid Build Coastguard Worker         let additional_attestation_info = [KeyParam::ModuleHash(vec![0xaa; 32])];
1420*9860b763SAndroid Build Coastguard Worker         let authz_list = AuthorizationList::new(
1421*9860b763SAndroid Build Coastguard Worker             &[KeyParam::Algorithm(keymint::Algorithm::Ec)],
1422*9860b763SAndroid Build Coastguard Worker             &[],
1423*9860b763SAndroid Build Coastguard Worker             None,
1424*9860b763SAndroid Build Coastguard Worker             Some(RootOfTrust {
1425*9860b763SAndroid Build Coastguard Worker                 verified_boot_key: &[0xbbu8; 32],
1426*9860b763SAndroid Build Coastguard Worker                 device_locked: false,
1427*9860b763SAndroid Build Coastguard Worker                 verified_boot_state: VerifiedBootState::Unverified,
1428*9860b763SAndroid Build Coastguard Worker                 verified_boot_hash: &[0xee; 32],
1429*9860b763SAndroid Build Coastguard Worker             }),
1430*9860b763SAndroid Build Coastguard Worker             None,
1431*9860b763SAndroid Build Coastguard Worker             &additional_attestation_info,
1432*9860b763SAndroid Build Coastguard Worker         )
1433*9860b763SAndroid Build Coastguard Worker         .unwrap();
1434*9860b763SAndroid Build Coastguard Worker         let got = authz_list.to_der().unwrap();
1435*9860b763SAndroid Build Coastguard Worker         let want: &str = concat!(
1436*9860b763SAndroid Build Coastguard Worker             "307b", // SEQUENCE len 123
1437*9860b763SAndroid Build Coastguard Worker             "a203", // EXPLICIT [2]
1438*9860b763SAndroid Build Coastguard Worker             "0201", // INTEGER len 1
1439*9860b763SAndroid Build Coastguard Worker             "03",   // 3 (Algorithm::Ec)
1440*9860b763SAndroid Build Coastguard Worker             "bf8540",
1441*9860b763SAndroid Build Coastguard Worker             "4c",   // EXPLICIT [704] len 0x4c
1442*9860b763SAndroid Build Coastguard Worker             "304a", // SEQUENCE len x4a
1443*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1444*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1445*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1446*9860b763SAndroid Build Coastguard Worker             "0101", // BOOLEAN len 1
1447*9860b763SAndroid Build Coastguard Worker             "00",   // false
1448*9860b763SAndroid Build Coastguard Worker             "0a01", // ENUMERATED len 1
1449*9860b763SAndroid Build Coastguard Worker             "02",   // Unverified(2)
1450*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1451*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1452*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1453*9860b763SAndroid Build Coastguard Worker             "bf8554",
1454*9860b763SAndroid Build Coastguard Worker             "22",   // EXPLICIT [724] len 34
1455*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1456*9860b763SAndroid Build Coastguard Worker             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1457*9860b763SAndroid Build Coastguard Worker             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1458*9860b763SAndroid Build Coastguard Worker         );
1459*9860b763SAndroid Build Coastguard Worker         // encode
1460*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(&got), want);
1461*9860b763SAndroid Build Coastguard Worker         // decode from encoded
1462*9860b763SAndroid Build Coastguard Worker         assert_eq!(AuthorizationList::from_der(got.as_slice()).unwrap(), authz_list);
1463*9860b763SAndroid Build Coastguard Worker     }
1464*9860b763SAndroid Build Coastguard Worker 
1465*9860b763SAndroid Build Coastguard Worker     #[test]
test_authz_list_user_secure_id_encode()1466*9860b763SAndroid Build Coastguard Worker     fn test_authz_list_user_secure_id_encode() {
1467*9860b763SAndroid Build Coastguard Worker         // Create an authorization list that includes multiple values for SecureUserId.
1468*9860b763SAndroid Build Coastguard Worker         let authz_list = AuthorizationList::new(
1469*9860b763SAndroid Build Coastguard Worker             &[
1470*9860b763SAndroid Build Coastguard Worker                 KeyParam::Algorithm(keymint::Algorithm::Ec),
1471*9860b763SAndroid Build Coastguard Worker                 KeyParam::UserSecureId(42),
1472*9860b763SAndroid Build Coastguard Worker                 KeyParam::UserSecureId(43),
1473*9860b763SAndroid Build Coastguard Worker                 KeyParam::UserSecureId(44),
1474*9860b763SAndroid Build Coastguard Worker             ],
1475*9860b763SAndroid Build Coastguard Worker             &[],
1476*9860b763SAndroid Build Coastguard Worker             None,
1477*9860b763SAndroid Build Coastguard Worker             Some(RootOfTrust {
1478*9860b763SAndroid Build Coastguard Worker                 verified_boot_key: &[0xbbu8; 32],
1479*9860b763SAndroid Build Coastguard Worker                 device_locked: false,
1480*9860b763SAndroid Build Coastguard Worker                 verified_boot_state: VerifiedBootState::Unverified,
1481*9860b763SAndroid Build Coastguard Worker                 verified_boot_hash: &[0xee; 32],
1482*9860b763SAndroid Build Coastguard Worker             }),
1483*9860b763SAndroid Build Coastguard Worker             None,
1484*9860b763SAndroid Build Coastguard Worker             &[],
1485*9860b763SAndroid Build Coastguard Worker         )
1486*9860b763SAndroid Build Coastguard Worker         .unwrap();
1487*9860b763SAndroid Build Coastguard Worker         let got = authz_list.to_der().unwrap();
1488*9860b763SAndroid Build Coastguard Worker         // The `SecureUserId` values are *not* included in the generated output.
1489*9860b763SAndroid Build Coastguard Worker         let want: &str = concat!(
1490*9860b763SAndroid Build Coastguard Worker             "3055", // SEQUENCE len 55
1491*9860b763SAndroid Build Coastguard Worker             "a203", // EXPLICIT [2]
1492*9860b763SAndroid Build Coastguard Worker             "0201", // INTEGER len 1
1493*9860b763SAndroid Build Coastguard Worker             "03",   // 3 (Algorithm::Ec)
1494*9860b763SAndroid Build Coastguard Worker             "bf8540",
1495*9860b763SAndroid Build Coastguard Worker             "4c",   // EXPLICIT [704] len 0x4c
1496*9860b763SAndroid Build Coastguard Worker             "304a", // SEQUENCE len x4a
1497*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1498*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1499*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1500*9860b763SAndroid Build Coastguard Worker             "0101", // BOOLEAN len 1
1501*9860b763SAndroid Build Coastguard Worker             "00",   // false
1502*9860b763SAndroid Build Coastguard Worker             "0a01", // ENUMERATED len 1
1503*9860b763SAndroid Build Coastguard Worker             "02",   // Unverified(2)
1504*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1505*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1506*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1507*9860b763SAndroid Build Coastguard Worker         );
1508*9860b763SAndroid Build Coastguard Worker         // encode
1509*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(got), want);
1510*9860b763SAndroid Build Coastguard Worker     }
1511*9860b763SAndroid Build Coastguard Worker 
1512*9860b763SAndroid Build Coastguard Worker     #[test]
test_authz_list_user_secure_id_decode()1513*9860b763SAndroid Build Coastguard Worker     fn test_authz_list_user_secure_id_decode() {
1514*9860b763SAndroid Build Coastguard Worker         // Create a DER-encoded `AuthorizationList` that includes a `UserSecureId` value.
1515*9860b763SAndroid Build Coastguard Worker         let input = hex::decode(concat!(
1516*9860b763SAndroid Build Coastguard Worker             "305c",   // SEQUENCE
1517*9860b763SAndroid Build Coastguard Worker             "a203",   // EXPLICIT [2] len 3
1518*9860b763SAndroid Build Coastguard Worker             "0201",   // INTEGER len 1
1519*9860b763SAndroid Build Coastguard Worker             "03",     // 3 (Algorithm::Ec)
1520*9860b763SAndroid Build Coastguard Worker             "bf8376", // EXPLICIT [502]
1521*9860b763SAndroid Build Coastguard Worker             "03",     // len 3
1522*9860b763SAndroid Build Coastguard Worker             "0201",   // INTEGER len 1
1523*9860b763SAndroid Build Coastguard Worker             "02",     // 2
1524*9860b763SAndroid Build Coastguard Worker             "bf8540", // EXPLICIT [704]
1525*9860b763SAndroid Build Coastguard Worker             "4c",     // len 0x4c
1526*9860b763SAndroid Build Coastguard Worker             "304a",   // SEQUENCE len x4a
1527*9860b763SAndroid Build Coastguard Worker             "0420",   // OCTET STRING len 32
1528*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1529*9860b763SAndroid Build Coastguard Worker             "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
1530*9860b763SAndroid Build Coastguard Worker             "0101", // BOOLEAN len 1
1531*9860b763SAndroid Build Coastguard Worker             "00",   // false
1532*9860b763SAndroid Build Coastguard Worker             "0a01", // ENUMERATED len 1
1533*9860b763SAndroid Build Coastguard Worker             "02",   // Unverified(2)
1534*9860b763SAndroid Build Coastguard Worker             "0420", // OCTET STRING len 32
1535*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1536*9860b763SAndroid Build Coastguard Worker             "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
1537*9860b763SAndroid Build Coastguard Worker         ))
1538*9860b763SAndroid Build Coastguard Worker         .unwrap();
1539*9860b763SAndroid Build Coastguard Worker         let got = AuthorizationList::from_der(&input).unwrap();
1540*9860b763SAndroid Build Coastguard Worker 
1541*9860b763SAndroid Build Coastguard Worker         let want = AuthorizationList::new(
1542*9860b763SAndroid Build Coastguard Worker             &[KeyParam::Algorithm(keymint::Algorithm::Ec), KeyParam::UserSecureId(2)],
1543*9860b763SAndroid Build Coastguard Worker             &[],
1544*9860b763SAndroid Build Coastguard Worker             None,
1545*9860b763SAndroid Build Coastguard Worker             Some(RootOfTrust {
1546*9860b763SAndroid Build Coastguard Worker                 verified_boot_key: &[0xbbu8; 32],
1547*9860b763SAndroid Build Coastguard Worker                 device_locked: false,
1548*9860b763SAndroid Build Coastguard Worker                 verified_boot_state: VerifiedBootState::Unverified,
1549*9860b763SAndroid Build Coastguard Worker                 verified_boot_hash: &[0xee; 32],
1550*9860b763SAndroid Build Coastguard Worker             }),
1551*9860b763SAndroid Build Coastguard Worker             None,
1552*9860b763SAndroid Build Coastguard Worker             &[],
1553*9860b763SAndroid Build Coastguard Worker         )
1554*9860b763SAndroid Build Coastguard Worker         .unwrap();
1555*9860b763SAndroid Build Coastguard Worker 
1556*9860b763SAndroid Build Coastguard Worker         assert_eq!(got, want);
1557*9860b763SAndroid Build Coastguard Worker     }
1558*9860b763SAndroid Build Coastguard Worker 
1559*9860b763SAndroid Build Coastguard Worker     #[test]
test_authz_list_dup_encode()1560*9860b763SAndroid Build Coastguard Worker     fn test_authz_list_dup_encode() {
1561*9860b763SAndroid Build Coastguard Worker         use kmr_wire::keymint::Digest;
1562*9860b763SAndroid Build Coastguard Worker         let authz_list = AuthorizationList::new(
1563*9860b763SAndroid Build Coastguard Worker             &[
1564*9860b763SAndroid Build Coastguard Worker                 KeyParam::Digest(Digest::None),
1565*9860b763SAndroid Build Coastguard Worker                 KeyParam::Digest(Digest::Sha1),
1566*9860b763SAndroid Build Coastguard Worker                 KeyParam::Digest(Digest::Sha1), // duplicate value
1567*9860b763SAndroid Build Coastguard Worker             ],
1568*9860b763SAndroid Build Coastguard Worker             &[],
1569*9860b763SAndroid Build Coastguard Worker             None,
1570*9860b763SAndroid Build Coastguard Worker             Some(RootOfTrust {
1571*9860b763SAndroid Build Coastguard Worker                 verified_boot_key: &[0xbbu8; 32],
1572*9860b763SAndroid Build Coastguard Worker                 device_locked: false,
1573*9860b763SAndroid Build Coastguard Worker                 verified_boot_state: VerifiedBootState::Unverified,
1574*9860b763SAndroid Build Coastguard Worker                 verified_boot_hash: &[0xee; 32],
1575*9860b763SAndroid Build Coastguard Worker             }),
1576*9860b763SAndroid Build Coastguard Worker             None,
1577*9860b763SAndroid Build Coastguard Worker             &[],
1578*9860b763SAndroid Build Coastguard Worker         )
1579*9860b763SAndroid Build Coastguard Worker         .unwrap();
1580*9860b763SAndroid Build Coastguard Worker         let got = authz_list.to_der().unwrap();
1581*9860b763SAndroid Build Coastguard Worker         assert!(AuthorizationList::from_der(got.as_slice()).is_ok());
1582*9860b763SAndroid Build Coastguard Worker     }
1583*9860b763SAndroid Build Coastguard Worker 
1584*9860b763SAndroid Build Coastguard Worker     #[test]
test_authz_list_order_fail()1585*9860b763SAndroid Build Coastguard Worker     fn test_authz_list_order_fail() {
1586*9860b763SAndroid Build Coastguard Worker         use kmr_wire::keymint::Digest;
1587*9860b763SAndroid Build Coastguard Worker         let authz_list = AuthorizationList::new(
1588*9860b763SAndroid Build Coastguard Worker             &[KeyParam::Digest(Digest::Sha1), KeyParam::Digest(Digest::None)],
1589*9860b763SAndroid Build Coastguard Worker             &[],
1590*9860b763SAndroid Build Coastguard Worker             None,
1591*9860b763SAndroid Build Coastguard Worker             Some(RootOfTrust {
1592*9860b763SAndroid Build Coastguard Worker                 verified_boot_key: &[0xbbu8; 32],
1593*9860b763SAndroid Build Coastguard Worker                 device_locked: false,
1594*9860b763SAndroid Build Coastguard Worker                 verified_boot_state: VerifiedBootState::Unverified,
1595*9860b763SAndroid Build Coastguard Worker                 verified_boot_hash: &[0xee; 32],
1596*9860b763SAndroid Build Coastguard Worker             }),
1597*9860b763SAndroid Build Coastguard Worker             None,
1598*9860b763SAndroid Build Coastguard Worker             &[],
1599*9860b763SAndroid Build Coastguard Worker         )
1600*9860b763SAndroid Build Coastguard Worker         .unwrap();
1601*9860b763SAndroid Build Coastguard Worker         assert!(authz_list.to_der().is_err());
1602*9860b763SAndroid Build Coastguard Worker     }
1603*9860b763SAndroid Build Coastguard Worker }
1604