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