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 //! TA functionality related to key generation/import/upgrade. 16*9860b763SAndroid Build Coastguard Worker 17*9860b763SAndroid Build Coastguard Worker use crate::{cert, device, AttestationChainInfo}; 18*9860b763SAndroid Build Coastguard Worker use alloc::collections::btree_map::Entry; 19*9860b763SAndroid Build Coastguard Worker use alloc::vec::Vec; 20*9860b763SAndroid Build Coastguard Worker use core::{borrow::Borrow, cmp::Ordering, convert::TryFrom}; 21*9860b763SAndroid Build Coastguard Worker use der::{referenced::RefToOwned, Decode, Sequence}; 22*9860b763SAndroid Build Coastguard Worker use kmr_common::{ 23*9860b763SAndroid Build Coastguard Worker crypto::{self, aes, rsa, KeyMaterial, OpaqueOr}, 24*9860b763SAndroid Build Coastguard Worker der_err, get_bool_tag_value, get_opt_tag_value, get_tag_value, keyblob, km_err, tag, 25*9860b763SAndroid Build Coastguard Worker try_to_vec, vec_try_with_capacity, Error, FallibleAllocExt, 26*9860b763SAndroid Build Coastguard Worker }; 27*9860b763SAndroid Build Coastguard Worker use kmr_wire::{ 28*9860b763SAndroid Build Coastguard Worker keymint::{ 29*9860b763SAndroid Build Coastguard Worker AttestationKey, Digest, EcCurve, ErrorCode, HardwareAuthenticatorType, KeyCharacteristics, 30*9860b763SAndroid Build Coastguard Worker KeyCreationResult, KeyFormat, KeyOrigin, KeyParam, KeyPurpose, SecurityLevel, 31*9860b763SAndroid Build Coastguard Worker UNDEFINED_NOT_AFTER, UNDEFINED_NOT_BEFORE, 32*9860b763SAndroid Build Coastguard Worker }, 33*9860b763SAndroid Build Coastguard Worker *, 34*9860b763SAndroid Build Coastguard Worker }; 35*9860b763SAndroid Build Coastguard Worker use log::{error, warn}; 36*9860b763SAndroid Build Coastguard Worker use spki::SubjectPublicKeyInfoOwned; 37*9860b763SAndroid Build Coastguard Worker use x509_cert::ext::pkix::KeyUsages; 38*9860b763SAndroid Build Coastguard Worker 39*9860b763SAndroid Build Coastguard Worker /// Maximum size of an attestation challenge value. 40*9860b763SAndroid Build Coastguard Worker const MAX_ATTESTATION_CHALLENGE_LEN: usize = 128; 41*9860b763SAndroid Build Coastguard Worker 42*9860b763SAndroid Build Coastguard Worker /// Contents of wrapping key data 43*9860b763SAndroid Build Coastguard Worker /// 44*9860b763SAndroid Build Coastguard Worker /// ```asn1 45*9860b763SAndroid Build Coastguard Worker /// SecureKeyWrapper ::= SEQUENCE { 46*9860b763SAndroid Build Coastguard Worker /// version INTEGER, # Value 0 47*9860b763SAndroid Build Coastguard Worker /// encryptedTransportKey OCTET_STRING, 48*9860b763SAndroid Build Coastguard Worker /// initializationVector OCTET_STRING, 49*9860b763SAndroid Build Coastguard Worker /// keyDescription KeyDescription, # See below 50*9860b763SAndroid Build Coastguard Worker /// encryptedKey OCTET_STRING, 51*9860b763SAndroid Build Coastguard Worker /// tag OCTET_STRING, 52*9860b763SAndroid Build Coastguard Worker /// } 53*9860b763SAndroid Build Coastguard Worker /// ``` 54*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Sequence)] 55*9860b763SAndroid Build Coastguard Worker pub struct SecureKeyWrapper<'a> { 56*9860b763SAndroid Build Coastguard Worker /// Version of this structure. 57*9860b763SAndroid Build Coastguard Worker pub version: i32, 58*9860b763SAndroid Build Coastguard Worker /// Encrypted transport key. 59*9860b763SAndroid Build Coastguard Worker #[asn1(type = "OCTET STRING")] 60*9860b763SAndroid Build Coastguard Worker pub encrypted_transport_key: &'a [u8], 61*9860b763SAndroid Build Coastguard Worker /// IV to use for decryption. 62*9860b763SAndroid Build Coastguard Worker #[asn1(type = "OCTET STRING")] 63*9860b763SAndroid Build Coastguard Worker pub initialization_vector: &'a [u8], 64*9860b763SAndroid Build Coastguard Worker /// Key parameters and description. 65*9860b763SAndroid Build Coastguard Worker pub key_description: KeyDescription<'a>, 66*9860b763SAndroid Build Coastguard Worker /// Ciphertext of the imported key. 67*9860b763SAndroid Build Coastguard Worker #[asn1(type = "OCTET STRING")] 68*9860b763SAndroid Build Coastguard Worker pub encrypted_key: &'a [u8], 69*9860b763SAndroid Build Coastguard Worker /// Tag value. 70*9860b763SAndroid Build Coastguard Worker #[asn1(type = "OCTET STRING")] 71*9860b763SAndroid Build Coastguard Worker pub tag: &'a [u8], 72*9860b763SAndroid Build Coastguard Worker } 73*9860b763SAndroid Build Coastguard Worker 74*9860b763SAndroid Build Coastguard Worker const SECURE_KEY_WRAPPER_VERSION: i32 = 0; 75*9860b763SAndroid Build Coastguard Worker 76*9860b763SAndroid Build Coastguard Worker /// Contents of key description. 77*9860b763SAndroid Build Coastguard Worker /// 78*9860b763SAndroid Build Coastguard Worker /// ```asn1 79*9860b763SAndroid Build Coastguard Worker /// KeyDescription ::= SEQUENCE { 80*9860b763SAndroid Build Coastguard Worker /// keyFormat INTEGER, # Values from KeyFormat enum 81*9860b763SAndroid Build Coastguard Worker /// keyParams AuthorizationList, # See cert.rs 82*9860b763SAndroid Build Coastguard Worker /// } 83*9860b763SAndroid Build Coastguard Worker /// ``` 84*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Sequence)] 85*9860b763SAndroid Build Coastguard Worker pub struct KeyDescription<'a> { 86*9860b763SAndroid Build Coastguard Worker /// Format of imported key. 87*9860b763SAndroid Build Coastguard Worker pub key_format: i32, 88*9860b763SAndroid Build Coastguard Worker /// Key parameters. 89*9860b763SAndroid Build Coastguard Worker pub key_params: cert::AuthorizationList<'a>, 90*9860b763SAndroid Build Coastguard Worker } 91*9860b763SAndroid Build Coastguard Worker 92*9860b763SAndroid Build Coastguard Worker /// Indication of whether key import has a secure wrapper. 93*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy)] 94*9860b763SAndroid Build Coastguard Worker pub(crate) enum KeyImport { 95*9860b763SAndroid Build Coastguard Worker Wrapped, 96*9860b763SAndroid Build Coastguard Worker NonWrapped, 97*9860b763SAndroid Build Coastguard Worker } 98*9860b763SAndroid Build Coastguard Worker 99*9860b763SAndroid Build Coastguard Worker /// Combined information needed for signing a fresh public key. 100*9860b763SAndroid Build Coastguard Worker #[derive(Clone)] 101*9860b763SAndroid Build Coastguard Worker pub(crate) struct SigningInfo<'a> { 102*9860b763SAndroid Build Coastguard Worker pub attestation_info: Option<(&'a [u8], &'a [u8])>, // (challenge, app_id) 103*9860b763SAndroid Build Coastguard Worker pub signing_key: KeyMaterial, 104*9860b763SAndroid Build Coastguard Worker /// ASN.1 DER encoding of subject field from first cert. 105*9860b763SAndroid Build Coastguard Worker pub issuer_subject: Vec<u8>, 106*9860b763SAndroid Build Coastguard Worker /// Cert chain starting with public key for `signing_key`. 107*9860b763SAndroid Build Coastguard Worker pub chain: Vec<keymint::Certificate>, 108*9860b763SAndroid Build Coastguard Worker } 109*9860b763SAndroid Build Coastguard Worker 110*9860b763SAndroid Build Coastguard Worker impl crate::KeyMintTa { 111*9860b763SAndroid Build Coastguard Worker /// Retrieve the signing information. get_signing_info( &self, key_type: device::SigningKeyType, ) -> Result<SigningInfo, Error>112*9860b763SAndroid Build Coastguard Worker pub(crate) fn get_signing_info( 113*9860b763SAndroid Build Coastguard Worker &self, 114*9860b763SAndroid Build Coastguard Worker key_type: device::SigningKeyType, 115*9860b763SAndroid Build Coastguard Worker ) -> Result<SigningInfo, Error> { 116*9860b763SAndroid Build Coastguard Worker let sign_info = self.dev.sign_info.as_ref().ok_or_else(|| { 117*9860b763SAndroid Build Coastguard Worker km_err!(AttestationKeysNotProvisioned, "batch attestation keys not available") 118*9860b763SAndroid Build Coastguard Worker })?; 119*9860b763SAndroid Build Coastguard Worker // Retrieve the chain and issuer information, which is cached after first retrieval. 120*9860b763SAndroid Build Coastguard Worker let mut attestation_chain_info = self.attestation_chain_info.borrow_mut(); 121*9860b763SAndroid Build Coastguard Worker let chain_info = match attestation_chain_info.entry(key_type) { 122*9860b763SAndroid Build Coastguard Worker Entry::Occupied(e) => e.into_mut(), 123*9860b763SAndroid Build Coastguard Worker Entry::Vacant(e) => { 124*9860b763SAndroid Build Coastguard Worker // Retrieve and store the cert chain information (as this is public). 125*9860b763SAndroid Build Coastguard Worker let chain = sign_info.cert_chain(key_type)?; 126*9860b763SAndroid Build Coastguard Worker let issuer = 127*9860b763SAndroid Build Coastguard Worker cert::extract_subject(chain.first().ok_or_else(|| { 128*9860b763SAndroid Build Coastguard Worker km_err!(KeymintNotConfigured, "empty attestation chain") 129*9860b763SAndroid Build Coastguard Worker })?)?; 130*9860b763SAndroid Build Coastguard Worker e.insert(AttestationChainInfo { chain, issuer }) 131*9860b763SAndroid Build Coastguard Worker } 132*9860b763SAndroid Build Coastguard Worker }; 133*9860b763SAndroid Build Coastguard Worker 134*9860b763SAndroid Build Coastguard Worker // Retrieve the signing key information (which will be dropped when signing is done). 135*9860b763SAndroid Build Coastguard Worker let signing_key = sign_info.signing_key(key_type)?; 136*9860b763SAndroid Build Coastguard Worker Ok(SigningInfo { 137*9860b763SAndroid Build Coastguard Worker attestation_info: None, 138*9860b763SAndroid Build Coastguard Worker signing_key, 139*9860b763SAndroid Build Coastguard Worker issuer_subject: chain_info.issuer.clone(), 140*9860b763SAndroid Build Coastguard Worker chain: chain_info.chain.clone(), 141*9860b763SAndroid Build Coastguard Worker }) 142*9860b763SAndroid Build Coastguard Worker } 143*9860b763SAndroid Build Coastguard Worker 144*9860b763SAndroid Build Coastguard Worker /// Generate an X.509 leaf certificate. generate_cert( &self, info: Option<SigningInfo>, spki: SubjectPublicKeyInfoOwned, params: &[KeyParam], chars: &[KeyCharacteristics], ) -> Result<keymint::Certificate, Error>145*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_cert( 146*9860b763SAndroid Build Coastguard Worker &self, 147*9860b763SAndroid Build Coastguard Worker info: Option<SigningInfo>, 148*9860b763SAndroid Build Coastguard Worker spki: SubjectPublicKeyInfoOwned, 149*9860b763SAndroid Build Coastguard Worker params: &[KeyParam], 150*9860b763SAndroid Build Coastguard Worker chars: &[KeyCharacteristics], 151*9860b763SAndroid Build Coastguard Worker ) -> Result<keymint::Certificate, Error> { 152*9860b763SAndroid Build Coastguard Worker // Build and encode key usage extension value 153*9860b763SAndroid Build Coastguard Worker let key_usage_ext_bits = cert::key_usage_extension_bits(params); 154*9860b763SAndroid Build Coastguard Worker let key_usage_ext_val = cert::asn1_der_encode(&key_usage_ext_bits) 155*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to encode KeyUsage {:?}", key_usage_ext_bits))?; 156*9860b763SAndroid Build Coastguard Worker 157*9860b763SAndroid Build Coastguard Worker // Build and encode basic constraints extension value, based on the key usage extension 158*9860b763SAndroid Build Coastguard Worker // value 159*9860b763SAndroid Build Coastguard Worker let basic_constraints_ext_val = 160*9860b763SAndroid Build Coastguard Worker if (key_usage_ext_bits.0 & KeyUsages::KeyCertSign).bits().count_ones() != 0 { 161*9860b763SAndroid Build Coastguard Worker let basic_constraints = cert::basic_constraints_ext_value(true); 162*9860b763SAndroid Build Coastguard Worker Some(cert::asn1_der_encode(&basic_constraints).map_err(|e| { 163*9860b763SAndroid Build Coastguard Worker der_err!(e, "failed to encode basic constraints {:?}", basic_constraints) 164*9860b763SAndroid Build Coastguard Worker })?) 165*9860b763SAndroid Build Coastguard Worker } else { 166*9860b763SAndroid Build Coastguard Worker None 167*9860b763SAndroid Build Coastguard Worker }; 168*9860b763SAndroid Build Coastguard Worker 169*9860b763SAndroid Build Coastguard Worker // Build and encode attestation extension if present 170*9860b763SAndroid Build Coastguard Worker let id_info = self.get_attestation_ids(); 171*9860b763SAndroid Build Coastguard Worker let attest_ext_val = 172*9860b763SAndroid Build Coastguard Worker if let Some(SigningInfo { attestation_info: Some((challenge, app_id)), .. }) = &info { 173*9860b763SAndroid Build Coastguard Worker let unique_id = self.calculate_unique_id(app_id, params)?; 174*9860b763SAndroid Build Coastguard Worker let boot_info = self.boot_info_hashed_key()?; 175*9860b763SAndroid Build Coastguard Worker let attest_ext = cert::attestation_extension( 176*9860b763SAndroid Build Coastguard Worker self.aidl_version as i32, 177*9860b763SAndroid Build Coastguard Worker challenge, 178*9860b763SAndroid Build Coastguard Worker app_id, 179*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 180*9860b763SAndroid Build Coastguard Worker id_info.as_ref().map(|v| v.borrow()), 181*9860b763SAndroid Build Coastguard Worker params, 182*9860b763SAndroid Build Coastguard Worker chars, 183*9860b763SAndroid Build Coastguard Worker &unique_id, 184*9860b763SAndroid Build Coastguard Worker &boot_info, 185*9860b763SAndroid Build Coastguard Worker &self.additional_attestation_info, 186*9860b763SAndroid Build Coastguard Worker )?; 187*9860b763SAndroid Build Coastguard Worker Some( 188*9860b763SAndroid Build Coastguard Worker cert::asn1_der_encode(&attest_ext) 189*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to encode attestation extension"))?, 190*9860b763SAndroid Build Coastguard Worker ) 191*9860b763SAndroid Build Coastguard Worker } else { 192*9860b763SAndroid Build Coastguard Worker None 193*9860b763SAndroid Build Coastguard Worker }; 194*9860b763SAndroid Build Coastguard Worker 195*9860b763SAndroid Build Coastguard Worker let tbs_cert = cert::tbs_certificate( 196*9860b763SAndroid Build Coastguard Worker &info, 197*9860b763SAndroid Build Coastguard Worker spki, 198*9860b763SAndroid Build Coastguard Worker &key_usage_ext_val, 199*9860b763SAndroid Build Coastguard Worker basic_constraints_ext_val.as_deref(), 200*9860b763SAndroid Build Coastguard Worker attest_ext_val.as_deref(), 201*9860b763SAndroid Build Coastguard Worker tag::characteristics_at(chars, self.hw_info.security_level)?, 202*9860b763SAndroid Build Coastguard Worker params, 203*9860b763SAndroid Build Coastguard Worker )?; 204*9860b763SAndroid Build Coastguard Worker let tbs_data = cert::asn1_der_encode(&tbs_cert) 205*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to encode tbsCert"))?; 206*9860b763SAndroid Build Coastguard Worker // If key does not have ATTEST_KEY or SIGN purpose, the certificate has empty signature 207*9860b763SAndroid Build Coastguard Worker let sig_data = match info.as_ref() { 208*9860b763SAndroid Build Coastguard Worker Some(info) => self.sign_cert_data(info.signing_key.clone(), tbs_data.as_slice())?, 209*9860b763SAndroid Build Coastguard Worker None => Vec::new(), 210*9860b763SAndroid Build Coastguard Worker }; 211*9860b763SAndroid Build Coastguard Worker 212*9860b763SAndroid Build Coastguard Worker let cert = cert::certificate(tbs_cert, &sig_data)?; 213*9860b763SAndroid Build Coastguard Worker let cert_data = cert::asn1_der_encode(&cert) 214*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to encode certificate"))?; 215*9860b763SAndroid Build Coastguard Worker Ok(keymint::Certificate { encoded_certificate: cert_data }) 216*9860b763SAndroid Build Coastguard Worker } 217*9860b763SAndroid Build Coastguard Worker 218*9860b763SAndroid Build Coastguard Worker /// Perform a complete signing operation using default modes. sign_cert_data(&self, signing_key: KeyMaterial, tbs_data: &[u8]) -> Result<Vec<u8>, Error>219*9860b763SAndroid Build Coastguard Worker fn sign_cert_data(&self, signing_key: KeyMaterial, tbs_data: &[u8]) -> Result<Vec<u8>, Error> { 220*9860b763SAndroid Build Coastguard Worker match signing_key { 221*9860b763SAndroid Build Coastguard Worker KeyMaterial::Rsa(key) => { 222*9860b763SAndroid Build Coastguard Worker let mut op = self 223*9860b763SAndroid Build Coastguard Worker .imp 224*9860b763SAndroid Build Coastguard Worker .rsa 225*9860b763SAndroid Build Coastguard Worker .begin_sign(key, rsa::SignMode::Pkcs1_1_5Padding(Digest::Sha256))?; 226*9860b763SAndroid Build Coastguard Worker op.update(tbs_data)?; 227*9860b763SAndroid Build Coastguard Worker op.finish() 228*9860b763SAndroid Build Coastguard Worker } 229*9860b763SAndroid Build Coastguard Worker KeyMaterial::Ec(curve, _, key) => { 230*9860b763SAndroid Build Coastguard Worker let digest = if curve == EcCurve::Curve25519 { 231*9860b763SAndroid Build Coastguard Worker // Ed25519 includes an internal digest and so does not use an external digest. 232*9860b763SAndroid Build Coastguard Worker Digest::None 233*9860b763SAndroid Build Coastguard Worker } else { 234*9860b763SAndroid Build Coastguard Worker Digest::Sha256 235*9860b763SAndroid Build Coastguard Worker }; 236*9860b763SAndroid Build Coastguard Worker let mut op = self.imp.ec.begin_sign(key, digest)?; 237*9860b763SAndroid Build Coastguard Worker op.update(tbs_data)?; 238*9860b763SAndroid Build Coastguard Worker op.finish() 239*9860b763SAndroid Build Coastguard Worker } 240*9860b763SAndroid Build Coastguard Worker _ => Err(km_err!(IncompatibleAlgorithm, "unexpected cert signing key type")), 241*9860b763SAndroid Build Coastguard Worker } 242*9860b763SAndroid Build Coastguard Worker } 243*9860b763SAndroid Build Coastguard Worker 244*9860b763SAndroid Build Coastguard Worker /// Calculate the `UNIQUE_ID` value for the parameters, if needed. calculate_unique_id(&self, app_id: &[u8], params: &[KeyParam]) -> Result<Vec<u8>, Error>245*9860b763SAndroid Build Coastguard Worker fn calculate_unique_id(&self, app_id: &[u8], params: &[KeyParam]) -> Result<Vec<u8>, Error> { 246*9860b763SAndroid Build Coastguard Worker if !get_bool_tag_value!(params, IncludeUniqueId)? { 247*9860b763SAndroid Build Coastguard Worker return Ok(Vec::new()); 248*9860b763SAndroid Build Coastguard Worker } 249*9860b763SAndroid Build Coastguard Worker let creation_datetime = 250*9860b763SAndroid Build Coastguard Worker get_tag_value!(params, CreationDatetime, ErrorCode::InvalidArgument)?; 251*9860b763SAndroid Build Coastguard Worker let rounded_datetime = creation_datetime.ms_since_epoch / 2_592_000_000i64; 252*9860b763SAndroid Build Coastguard Worker let datetime_data = rounded_datetime.to_ne_bytes(); 253*9860b763SAndroid Build Coastguard Worker 254*9860b763SAndroid Build Coastguard Worker let mut combined_input = vec_try_with_capacity!(datetime_data.len() + app_id.len() + 1)?; 255*9860b763SAndroid Build Coastguard Worker combined_input.extend_from_slice(&datetime_data[..]); 256*9860b763SAndroid Build Coastguard Worker combined_input.extend_from_slice(app_id); 257*9860b763SAndroid Build Coastguard Worker combined_input.push(u8::from(get_bool_tag_value!(params, ResetSinceIdRotation)?)); 258*9860b763SAndroid Build Coastguard Worker 259*9860b763SAndroid Build Coastguard Worker let hbk = self.dev.keys.unique_id_hbk(&*self.imp.ckdf)?; 260*9860b763SAndroid Build Coastguard Worker 261*9860b763SAndroid Build Coastguard Worker let mut hmac_op = self.imp.hmac.begin(hbk.into(), Digest::Sha256)?; 262*9860b763SAndroid Build Coastguard Worker hmac_op.update(&combined_input)?; 263*9860b763SAndroid Build Coastguard Worker let tag = hmac_op.finish()?; 264*9860b763SAndroid Build Coastguard Worker try_to_vec(&tag[..16]) 265*9860b763SAndroid Build Coastguard Worker } 266*9860b763SAndroid Build Coastguard Worker generate_key( &mut self, params: &[KeyParam], attestation_key: Option<AttestationKey>, ) -> Result<KeyCreationResult, Error>267*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_key( 268*9860b763SAndroid Build Coastguard Worker &mut self, 269*9860b763SAndroid Build Coastguard Worker params: &[KeyParam], 270*9860b763SAndroid Build Coastguard Worker attestation_key: Option<AttestationKey>, 271*9860b763SAndroid Build Coastguard Worker ) -> Result<KeyCreationResult, Error> { 272*9860b763SAndroid Build Coastguard Worker let (key_material, chars) = self.generate_key_material(params)?; 273*9860b763SAndroid Build Coastguard Worker self.finish_keyblob_creation( 274*9860b763SAndroid Build Coastguard Worker params, 275*9860b763SAndroid Build Coastguard Worker attestation_key, 276*9860b763SAndroid Build Coastguard Worker chars, 277*9860b763SAndroid Build Coastguard Worker key_material, 278*9860b763SAndroid Build Coastguard Worker keyblob::SlotPurpose::KeyGeneration, 279*9860b763SAndroid Build Coastguard Worker ) 280*9860b763SAndroid Build Coastguard Worker } 281*9860b763SAndroid Build Coastguard Worker generate_key_material( &mut self, params: &[KeyParam], ) -> Result<(KeyMaterial, Vec<KeyCharacteristics>), Error>282*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_key_material( 283*9860b763SAndroid Build Coastguard Worker &mut self, 284*9860b763SAndroid Build Coastguard Worker params: &[KeyParam], 285*9860b763SAndroid Build Coastguard Worker ) -> Result<(KeyMaterial, Vec<KeyCharacteristics>), Error> { 286*9860b763SAndroid Build Coastguard Worker let (mut chars, keygen_info) = tag::extract_key_gen_characteristics( 287*9860b763SAndroid Build Coastguard Worker self.secure_storage_available(), 288*9860b763SAndroid Build Coastguard Worker params, 289*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 290*9860b763SAndroid Build Coastguard Worker )?; 291*9860b763SAndroid Build Coastguard Worker self.add_keymint_tags(&mut chars, KeyOrigin::Generated)?; 292*9860b763SAndroid Build Coastguard Worker let key_material = match keygen_info { 293*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::Aes(variant) => { 294*9860b763SAndroid Build Coastguard Worker self.imp.aes.generate_key(&mut *self.imp.rng, variant, params)? 295*9860b763SAndroid Build Coastguard Worker } 296*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::TripleDes => { 297*9860b763SAndroid Build Coastguard Worker self.imp.des.generate_key(&mut *self.imp.rng, params)? 298*9860b763SAndroid Build Coastguard Worker } 299*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::Hmac(key_size) => { 300*9860b763SAndroid Build Coastguard Worker self.imp.hmac.generate_key(&mut *self.imp.rng, key_size, params)? 301*9860b763SAndroid Build Coastguard Worker } 302*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::Rsa(key_size, pub_exponent) => { 303*9860b763SAndroid Build Coastguard Worker self.imp.rsa.generate_key(&mut *self.imp.rng, key_size, pub_exponent, params)? 304*9860b763SAndroid Build Coastguard Worker } 305*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::NistEc(curve) => { 306*9860b763SAndroid Build Coastguard Worker self.imp.ec.generate_nist_key(&mut *self.imp.rng, curve, params)? 307*9860b763SAndroid Build Coastguard Worker } 308*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::Ed25519 => { 309*9860b763SAndroid Build Coastguard Worker self.imp.ec.generate_ed25519_key(&mut *self.imp.rng, params)? 310*9860b763SAndroid Build Coastguard Worker } 311*9860b763SAndroid Build Coastguard Worker crypto::KeyGenInfo::X25519 => { 312*9860b763SAndroid Build Coastguard Worker self.imp.ec.generate_x25519_key(&mut *self.imp.rng, params)? 313*9860b763SAndroid Build Coastguard Worker } 314*9860b763SAndroid Build Coastguard Worker }; 315*9860b763SAndroid Build Coastguard Worker Ok((key_material, chars)) 316*9860b763SAndroid Build Coastguard Worker } 317*9860b763SAndroid Build Coastguard Worker import_key( &mut self, params: &[KeyParam], key_format: KeyFormat, key_data: &[u8], attestation_key: Option<AttestationKey>, import_type: KeyImport, ) -> Result<KeyCreationResult, Error>318*9860b763SAndroid Build Coastguard Worker pub(crate) fn import_key( 319*9860b763SAndroid Build Coastguard Worker &mut self, 320*9860b763SAndroid Build Coastguard Worker params: &[KeyParam], 321*9860b763SAndroid Build Coastguard Worker key_format: KeyFormat, 322*9860b763SAndroid Build Coastguard Worker key_data: &[u8], 323*9860b763SAndroid Build Coastguard Worker attestation_key: Option<AttestationKey>, 324*9860b763SAndroid Build Coastguard Worker import_type: KeyImport, 325*9860b763SAndroid Build Coastguard Worker ) -> Result<KeyCreationResult, Error> { 326*9860b763SAndroid Build Coastguard Worker if !self.in_early_boot && get_bool_tag_value!(params, EarlyBootOnly)? { 327*9860b763SAndroid Build Coastguard Worker return Err(km_err!(EarlyBootEnded, "attempt to use EARLY_BOOT key after early boot")); 328*9860b763SAndroid Build Coastguard Worker } 329*9860b763SAndroid Build Coastguard Worker 330*9860b763SAndroid Build Coastguard Worker let (mut chars, key_material) = tag::extract_key_import_characteristics( 331*9860b763SAndroid Build Coastguard Worker &self.imp, 332*9860b763SAndroid Build Coastguard Worker self.secure_storage_available(), 333*9860b763SAndroid Build Coastguard Worker params, 334*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 335*9860b763SAndroid Build Coastguard Worker key_format, 336*9860b763SAndroid Build Coastguard Worker key_data, 337*9860b763SAndroid Build Coastguard Worker )?; 338*9860b763SAndroid Build Coastguard Worker match import_type { 339*9860b763SAndroid Build Coastguard Worker KeyImport::NonWrapped => { 340*9860b763SAndroid Build Coastguard Worker self.add_keymint_tags(&mut chars, KeyOrigin::Imported)?; 341*9860b763SAndroid Build Coastguard Worker } 342*9860b763SAndroid Build Coastguard Worker KeyImport::Wrapped => { 343*9860b763SAndroid Build Coastguard Worker self.add_keymint_tags(&mut chars, KeyOrigin::SecurelyImported)?; 344*9860b763SAndroid Build Coastguard Worker } 345*9860b763SAndroid Build Coastguard Worker } 346*9860b763SAndroid Build Coastguard Worker 347*9860b763SAndroid Build Coastguard Worker self.finish_keyblob_creation( 348*9860b763SAndroid Build Coastguard Worker params, 349*9860b763SAndroid Build Coastguard Worker attestation_key, 350*9860b763SAndroid Build Coastguard Worker chars, 351*9860b763SAndroid Build Coastguard Worker key_material, 352*9860b763SAndroid Build Coastguard Worker keyblob::SlotPurpose::KeyImport, 353*9860b763SAndroid Build Coastguard Worker ) 354*9860b763SAndroid Build Coastguard Worker } 355*9860b763SAndroid Build Coastguard Worker 356*9860b763SAndroid Build Coastguard Worker /// Perform common processing for keyblob creation (for both generation and import). finish_keyblob_creation( &mut self, params: &[KeyParam], attestation_key: Option<AttestationKey>, chars: Vec<KeyCharacteristics>, key_material: KeyMaterial, purpose: keyblob::SlotPurpose, ) -> Result<KeyCreationResult, Error>357*9860b763SAndroid Build Coastguard Worker pub fn finish_keyblob_creation( 358*9860b763SAndroid Build Coastguard Worker &mut self, 359*9860b763SAndroid Build Coastguard Worker params: &[KeyParam], 360*9860b763SAndroid Build Coastguard Worker attestation_key: Option<AttestationKey>, 361*9860b763SAndroid Build Coastguard Worker chars: Vec<KeyCharacteristics>, 362*9860b763SAndroid Build Coastguard Worker key_material: KeyMaterial, 363*9860b763SAndroid Build Coastguard Worker purpose: keyblob::SlotPurpose, 364*9860b763SAndroid Build Coastguard Worker ) -> Result<KeyCreationResult, Error> { 365*9860b763SAndroid Build Coastguard Worker let keyblob = keyblob::PlaintextKeyBlob { 366*9860b763SAndroid Build Coastguard Worker // Don't include any `SecurityLevel::Keystore` characteristics in the set that is bound 367*9860b763SAndroid Build Coastguard Worker // to the key. 368*9860b763SAndroid Build Coastguard Worker characteristics: chars 369*9860b763SAndroid Build Coastguard Worker .iter() 370*9860b763SAndroid Build Coastguard Worker .filter(|c| c.security_level != SecurityLevel::Keystore) 371*9860b763SAndroid Build Coastguard Worker .cloned() 372*9860b763SAndroid Build Coastguard Worker .collect(), 373*9860b763SAndroid Build Coastguard Worker key_material: key_material.clone(), 374*9860b763SAndroid Build Coastguard Worker }; 375*9860b763SAndroid Build Coastguard Worker let attest_keyblob; 376*9860b763SAndroid Build Coastguard Worker let mut certificate_chain = Vec::new(); 377*9860b763SAndroid Build Coastguard Worker if let Some(spki) = keyblob.key_material.subject_public_key_info( 378*9860b763SAndroid Build Coastguard Worker &mut Vec::<u8>::new(), 379*9860b763SAndroid Build Coastguard Worker &*self.imp.ec, 380*9860b763SAndroid Build Coastguard Worker &*self.imp.rsa, 381*9860b763SAndroid Build Coastguard Worker )? { 382*9860b763SAndroid Build Coastguard Worker // Asymmetric keys return the public key inside an X.509 certificate. 383*9860b763SAndroid Build Coastguard Worker // Need to determine: 384*9860b763SAndroid Build Coastguard Worker // - a key to sign the cert with (may be absent), together with any associated 385*9860b763SAndroid Build Coastguard Worker // cert chain to append 386*9860b763SAndroid Build Coastguard Worker // - whether to include an attestation extension 387*9860b763SAndroid Build Coastguard Worker let attest_challenge = get_opt_tag_value!(params, AttestationChallenge)?; 388*9860b763SAndroid Build Coastguard Worker 389*9860b763SAndroid Build Coastguard Worker let signing_info = if let Some(attest_challenge) = attest_challenge { 390*9860b763SAndroid Build Coastguard Worker // Attestation requested. 391*9860b763SAndroid Build Coastguard Worker if attest_challenge.len() > MAX_ATTESTATION_CHALLENGE_LEN { 392*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 393*9860b763SAndroid Build Coastguard Worker InvalidInputLength, 394*9860b763SAndroid Build Coastguard Worker "attestation challenge too large: {} bytes", 395*9860b763SAndroid Build Coastguard Worker attest_challenge.len() 396*9860b763SAndroid Build Coastguard Worker )); 397*9860b763SAndroid Build Coastguard Worker } 398*9860b763SAndroid Build Coastguard Worker let attest_app_id = get_opt_tag_value!(params, AttestationApplicationId)? 399*9860b763SAndroid Build Coastguard Worker .ok_or_else(|| { 400*9860b763SAndroid Build Coastguard Worker km_err!(AttestationApplicationIdMissing, "attestation requested") 401*9860b763SAndroid Build Coastguard Worker })?; 402*9860b763SAndroid Build Coastguard Worker let attestation_info: Option<(&[u8], &[u8])> = 403*9860b763SAndroid Build Coastguard Worker Some((attest_challenge, attest_app_id)); 404*9860b763SAndroid Build Coastguard Worker 405*9860b763SAndroid Build Coastguard Worker if let Some(attest_keyinfo) = attestation_key.as_ref() { 406*9860b763SAndroid Build Coastguard Worker // User-specified attestation key provided. 407*9860b763SAndroid Build Coastguard Worker (attest_keyblob, _) = self.keyblob_parse_decrypt( 408*9860b763SAndroid Build Coastguard Worker &attest_keyinfo.key_blob, 409*9860b763SAndroid Build Coastguard Worker &attest_keyinfo.attest_key_params, 410*9860b763SAndroid Build Coastguard Worker )?; 411*9860b763SAndroid Build Coastguard Worker attest_keyblob 412*9860b763SAndroid Build Coastguard Worker .suitable_for(KeyPurpose::AttestKey, self.hw_info.security_level)?; 413*9860b763SAndroid Build Coastguard Worker if attest_keyinfo.issuer_subject_name.is_empty() { 414*9860b763SAndroid Build Coastguard Worker return Err(km_err!(InvalidArgument, "empty subject name")); 415*9860b763SAndroid Build Coastguard Worker } 416*9860b763SAndroid Build Coastguard Worker Some(SigningInfo { 417*9860b763SAndroid Build Coastguard Worker attestation_info, 418*9860b763SAndroid Build Coastguard Worker signing_key: attest_keyblob.key_material, 419*9860b763SAndroid Build Coastguard Worker issuer_subject: attest_keyinfo.issuer_subject_name.clone(), 420*9860b763SAndroid Build Coastguard Worker chain: Vec::new(), 421*9860b763SAndroid Build Coastguard Worker }) 422*9860b763SAndroid Build Coastguard Worker } else { 423*9860b763SAndroid Build Coastguard Worker // Need to use a device key for attestation. Look up the relevant device key and 424*9860b763SAndroid Build Coastguard Worker // chain. 425*9860b763SAndroid Build Coastguard Worker let which_key = match ( 426*9860b763SAndroid Build Coastguard Worker get_bool_tag_value!(params, DeviceUniqueAttestation)?, 427*9860b763SAndroid Build Coastguard Worker self.is_strongbox(), 428*9860b763SAndroid Build Coastguard Worker ) { 429*9860b763SAndroid Build Coastguard Worker (false, _) => device::SigningKey::Batch, 430*9860b763SAndroid Build Coastguard Worker (true, true) => device::SigningKey::DeviceUnique, 431*9860b763SAndroid Build Coastguard Worker (true, false) => { 432*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 433*9860b763SAndroid Build Coastguard Worker InvalidArgument, 434*9860b763SAndroid Build Coastguard Worker "device unique attestation supported only by Strongbox TA" 435*9860b763SAndroid Build Coastguard Worker )) 436*9860b763SAndroid Build Coastguard Worker } 437*9860b763SAndroid Build Coastguard Worker }; 438*9860b763SAndroid Build Coastguard Worker // Provide an indication of what's going to be signed, to allow the 439*9860b763SAndroid Build Coastguard Worker // implementation to switch between EC and RSA signing keys if it so chooses. 440*9860b763SAndroid Build Coastguard Worker let algo_hint = match &keyblob.key_material { 441*9860b763SAndroid Build Coastguard Worker crypto::KeyMaterial::Rsa(_) => device::SigningAlgorithm::Rsa, 442*9860b763SAndroid Build Coastguard Worker crypto::KeyMaterial::Ec(_, _, _) => device::SigningAlgorithm::Ec, 443*9860b763SAndroid Build Coastguard Worker _ => return Err(km_err!(InvalidArgument, "unexpected key type!")), 444*9860b763SAndroid Build Coastguard Worker }; 445*9860b763SAndroid Build Coastguard Worker 446*9860b763SAndroid Build Coastguard Worker let mut info = self 447*9860b763SAndroid Build Coastguard Worker .get_signing_info(device::SigningKeyType { which: which_key, algo_hint })?; 448*9860b763SAndroid Build Coastguard Worker info.attestation_info = attestation_info; 449*9860b763SAndroid Build Coastguard Worker Some(info) 450*9860b763SAndroid Build Coastguard Worker } 451*9860b763SAndroid Build Coastguard Worker } else { 452*9860b763SAndroid Build Coastguard Worker // No attestation challenge, so no attestation. 453*9860b763SAndroid Build Coastguard Worker if attestation_key.is_some() { 454*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 455*9860b763SAndroid Build Coastguard Worker AttestationChallengeMissing, 456*9860b763SAndroid Build Coastguard Worker "got attestation key but no challenge" 457*9860b763SAndroid Build Coastguard Worker )); 458*9860b763SAndroid Build Coastguard Worker } 459*9860b763SAndroid Build Coastguard Worker 460*9860b763SAndroid Build Coastguard Worker // See if the generated key can self-sign. 461*9860b763SAndroid Build Coastguard Worker let is_signing_key = params.iter().any(|param| { 462*9860b763SAndroid Build Coastguard Worker matches!( 463*9860b763SAndroid Build Coastguard Worker param, 464*9860b763SAndroid Build Coastguard Worker KeyParam::Purpose(KeyPurpose::Sign) 465*9860b763SAndroid Build Coastguard Worker | KeyParam::Purpose(KeyPurpose::AttestKey) 466*9860b763SAndroid Build Coastguard Worker ) 467*9860b763SAndroid Build Coastguard Worker }); 468*9860b763SAndroid Build Coastguard Worker if is_signing_key { 469*9860b763SAndroid Build Coastguard Worker Some(SigningInfo { 470*9860b763SAndroid Build Coastguard Worker attestation_info: None, 471*9860b763SAndroid Build Coastguard Worker signing_key: key_material, 472*9860b763SAndroid Build Coastguard Worker issuer_subject: try_to_vec(tag::get_cert_subject(params)?)?, 473*9860b763SAndroid Build Coastguard Worker chain: Vec::new(), 474*9860b763SAndroid Build Coastguard Worker }) 475*9860b763SAndroid Build Coastguard Worker } else { 476*9860b763SAndroid Build Coastguard Worker None 477*9860b763SAndroid Build Coastguard Worker } 478*9860b763SAndroid Build Coastguard Worker }; 479*9860b763SAndroid Build Coastguard Worker 480*9860b763SAndroid Build Coastguard Worker // Build the X.509 leaf certificate. 481*9860b763SAndroid Build Coastguard Worker let leaf_cert = 482*9860b763SAndroid Build Coastguard Worker self.generate_cert(signing_info.clone(), spki.ref_to_owned(), params, &chars)?; 483*9860b763SAndroid Build Coastguard Worker certificate_chain.try_push(leaf_cert)?; 484*9860b763SAndroid Build Coastguard Worker 485*9860b763SAndroid Build Coastguard Worker // Append the rest of the chain. 486*9860b763SAndroid Build Coastguard Worker if let Some(info) = signing_info { 487*9860b763SAndroid Build Coastguard Worker for cert in info.chain { 488*9860b763SAndroid Build Coastguard Worker certificate_chain.try_push(cert)?; 489*9860b763SAndroid Build Coastguard Worker } 490*9860b763SAndroid Build Coastguard Worker } 491*9860b763SAndroid Build Coastguard Worker } 492*9860b763SAndroid Build Coastguard Worker 493*9860b763SAndroid Build Coastguard Worker // Now build the keyblob. 494*9860b763SAndroid Build Coastguard Worker let kek_context = self.dev.keys.kek_context()?; 495*9860b763SAndroid Build Coastguard Worker let root_kek = self.root_kek(&kek_context)?; 496*9860b763SAndroid Build Coastguard Worker let hidden = tag::hidden(params, self.root_of_trust()?)?; 497*9860b763SAndroid Build Coastguard Worker let encrypted_keyblob = keyblob::encrypt( 498*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 499*9860b763SAndroid Build Coastguard Worker match &mut self.dev.sdd_mgr { 500*9860b763SAndroid Build Coastguard Worker None => None, 501*9860b763SAndroid Build Coastguard Worker Some(mr) => Some(&mut **mr), 502*9860b763SAndroid Build Coastguard Worker }, 503*9860b763SAndroid Build Coastguard Worker &*self.imp.aes, 504*9860b763SAndroid Build Coastguard Worker &*self.imp.hkdf, 505*9860b763SAndroid Build Coastguard Worker &mut *self.imp.rng, 506*9860b763SAndroid Build Coastguard Worker &root_kek, 507*9860b763SAndroid Build Coastguard Worker &kek_context, 508*9860b763SAndroid Build Coastguard Worker keyblob, 509*9860b763SAndroid Build Coastguard Worker hidden, 510*9860b763SAndroid Build Coastguard Worker purpose, 511*9860b763SAndroid Build Coastguard Worker )?; 512*9860b763SAndroid Build Coastguard Worker let serialized_keyblob = encrypted_keyblob.into_vec()?; 513*9860b763SAndroid Build Coastguard Worker 514*9860b763SAndroid Build Coastguard Worker Ok(KeyCreationResult { 515*9860b763SAndroid Build Coastguard Worker key_blob: serialized_keyblob, 516*9860b763SAndroid Build Coastguard Worker key_characteristics: chars, 517*9860b763SAndroid Build Coastguard Worker certificate_chain, 518*9860b763SAndroid Build Coastguard Worker }) 519*9860b763SAndroid Build Coastguard Worker } 520*9860b763SAndroid Build Coastguard Worker import_wrapped_key( &mut self, wrapped_key_data: &[u8], wrapping_key_blob: &[u8], masking_key: &[u8], unwrapping_params: &[KeyParam], password_sid: i64, biometric_sid: i64, ) -> Result<KeyCreationResult, Error>521*9860b763SAndroid Build Coastguard Worker pub(crate) fn import_wrapped_key( 522*9860b763SAndroid Build Coastguard Worker &mut self, 523*9860b763SAndroid Build Coastguard Worker wrapped_key_data: &[u8], 524*9860b763SAndroid Build Coastguard Worker wrapping_key_blob: &[u8], 525*9860b763SAndroid Build Coastguard Worker masking_key: &[u8], 526*9860b763SAndroid Build Coastguard Worker unwrapping_params: &[KeyParam], 527*9860b763SAndroid Build Coastguard Worker password_sid: i64, 528*9860b763SAndroid Build Coastguard Worker biometric_sid: i64, 529*9860b763SAndroid Build Coastguard Worker ) -> Result<KeyCreationResult, Error> { 530*9860b763SAndroid Build Coastguard Worker // Decrypt the wrapping key blob 531*9860b763SAndroid Build Coastguard Worker let (wrapping_key, _) = self.keyblob_parse_decrypt(wrapping_key_blob, unwrapping_params)?; 532*9860b763SAndroid Build Coastguard Worker let keyblob::PlaintextKeyBlob { characteristics, key_material } = wrapping_key; 533*9860b763SAndroid Build Coastguard Worker 534*9860b763SAndroid Build Coastguard Worker // Decode the ASN.1 DER encoded `SecureKeyWrapper`. 535*9860b763SAndroid Build Coastguard Worker let mut secure_key_wrapper = SecureKeyWrapper::from_der(wrapped_key_data) 536*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to parse SecureKeyWrapper"))?; 537*9860b763SAndroid Build Coastguard Worker 538*9860b763SAndroid Build Coastguard Worker if secure_key_wrapper.version != SECURE_KEY_WRAPPER_VERSION { 539*9860b763SAndroid Build Coastguard Worker return Err(km_err!(InvalidArgument, "invalid version in Secure Key Wrapper.")); 540*9860b763SAndroid Build Coastguard Worker } 541*9860b763SAndroid Build Coastguard Worker 542*9860b763SAndroid Build Coastguard Worker // Decrypt the masked transport key, using an RSA key. (Only RSA wrapping keys are supported 543*9860b763SAndroid Build Coastguard Worker // by the spec, as RSA is the only algorithm supporting asymmetric decryption.) 544*9860b763SAndroid Build Coastguard Worker let masked_transport_key = match key_material { 545*9860b763SAndroid Build Coastguard Worker KeyMaterial::Rsa(key) => { 546*9860b763SAndroid Build Coastguard Worker // Check the requirements on the wrapping key characterisitcs 547*9860b763SAndroid Build Coastguard Worker let decrypt_mode = tag::check_rsa_wrapping_key_params( 548*9860b763SAndroid Build Coastguard Worker tag::characteristics_at(&characteristics, self.hw_info.security_level)?, 549*9860b763SAndroid Build Coastguard Worker unwrapping_params, 550*9860b763SAndroid Build Coastguard Worker )?; 551*9860b763SAndroid Build Coastguard Worker 552*9860b763SAndroid Build Coastguard Worker // Decrypt the masked and encrypted transport key 553*9860b763SAndroid Build Coastguard Worker let mut crypto_op = self.imp.rsa.begin_decrypt(key, decrypt_mode)?; 554*9860b763SAndroid Build Coastguard Worker crypto_op.as_mut().update(secure_key_wrapper.encrypted_transport_key)?; 555*9860b763SAndroid Build Coastguard Worker crypto_op.finish()? 556*9860b763SAndroid Build Coastguard Worker } 557*9860b763SAndroid Build Coastguard Worker _ => { 558*9860b763SAndroid Build Coastguard Worker return Err(km_err!(InvalidArgument, "invalid key algorithm for transport key")); 559*9860b763SAndroid Build Coastguard Worker } 560*9860b763SAndroid Build Coastguard Worker }; 561*9860b763SAndroid Build Coastguard Worker 562*9860b763SAndroid Build Coastguard Worker if masked_transport_key.len() != masking_key.len() { 563*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 564*9860b763SAndroid Build Coastguard Worker InvalidArgument, 565*9860b763SAndroid Build Coastguard Worker "masked transport key is {} bytes, but masking key is {} bytes", 566*9860b763SAndroid Build Coastguard Worker masked_transport_key.len(), 567*9860b763SAndroid Build Coastguard Worker masking_key.len() 568*9860b763SAndroid Build Coastguard Worker )); 569*9860b763SAndroid Build Coastguard Worker } 570*9860b763SAndroid Build Coastguard Worker 571*9860b763SAndroid Build Coastguard Worker let unmasked_transport_key: Vec<u8> = 572*9860b763SAndroid Build Coastguard Worker masked_transport_key.iter().zip(masking_key).map(|(x, y)| x ^ y).collect(); 573*9860b763SAndroid Build Coastguard Worker 574*9860b763SAndroid Build Coastguard Worker let aes_transport_key = 575*9860b763SAndroid Build Coastguard Worker aes::Key::Aes256(unmasked_transport_key.try_into().map_err(|_e| { 576*9860b763SAndroid Build Coastguard Worker km_err!( 577*9860b763SAndroid Build Coastguard Worker InvalidArgument, 578*9860b763SAndroid Build Coastguard Worker "transport key len {} not correct for AES-256 key", 579*9860b763SAndroid Build Coastguard Worker masked_transport_key.len() 580*9860b763SAndroid Build Coastguard Worker ) 581*9860b763SAndroid Build Coastguard Worker })?); 582*9860b763SAndroid Build Coastguard Worker 583*9860b763SAndroid Build Coastguard Worker // Validate the size of the IV and match the `aes::GcmMode` based on the tag size. 584*9860b763SAndroid Build Coastguard Worker let iv_len = secure_key_wrapper.initialization_vector.len(); 585*9860b763SAndroid Build Coastguard Worker if iv_len != aes::GCM_NONCE_SIZE { 586*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 587*9860b763SAndroid Build Coastguard Worker InvalidArgument, 588*9860b763SAndroid Build Coastguard Worker "IV length is of {} bytes, which should be of {} bytes", 589*9860b763SAndroid Build Coastguard Worker iv_len, 590*9860b763SAndroid Build Coastguard Worker aes::GCM_NONCE_SIZE 591*9860b763SAndroid Build Coastguard Worker )); 592*9860b763SAndroid Build Coastguard Worker } 593*9860b763SAndroid Build Coastguard Worker let tag_len = secure_key_wrapper.tag.len(); 594*9860b763SAndroid Build Coastguard Worker let gcm_mode = match tag_len { 595*9860b763SAndroid Build Coastguard Worker 12 => crypto::aes::GcmMode::GcmTag12 { 596*9860b763SAndroid Build Coastguard Worker nonce: secure_key_wrapper.initialization_vector.try_into() 597*9860b763SAndroid Build Coastguard Worker .unwrap(/* safe: len checked */), 598*9860b763SAndroid Build Coastguard Worker }, 599*9860b763SAndroid Build Coastguard Worker 13 => crypto::aes::GcmMode::GcmTag13 { 600*9860b763SAndroid Build Coastguard Worker nonce: secure_key_wrapper.initialization_vector.try_into() 601*9860b763SAndroid Build Coastguard Worker .unwrap(/* safe: len checked */), 602*9860b763SAndroid Build Coastguard Worker }, 603*9860b763SAndroid Build Coastguard Worker 14 => crypto::aes::GcmMode::GcmTag14 { 604*9860b763SAndroid Build Coastguard Worker nonce: secure_key_wrapper.initialization_vector.try_into() 605*9860b763SAndroid Build Coastguard Worker .unwrap(/* safe: len checked */), 606*9860b763SAndroid Build Coastguard Worker }, 607*9860b763SAndroid Build Coastguard Worker 15 => crypto::aes::GcmMode::GcmTag15 { 608*9860b763SAndroid Build Coastguard Worker nonce: secure_key_wrapper.initialization_vector.try_into() 609*9860b763SAndroid Build Coastguard Worker .unwrap(/* safe: len checked */), 610*9860b763SAndroid Build Coastguard Worker }, 611*9860b763SAndroid Build Coastguard Worker 16 => crypto::aes::GcmMode::GcmTag16 { 612*9860b763SAndroid Build Coastguard Worker nonce: secure_key_wrapper.initialization_vector.try_into() 613*9860b763SAndroid Build Coastguard Worker .unwrap(/* safe: len checked */), 614*9860b763SAndroid Build Coastguard Worker }, 615*9860b763SAndroid Build Coastguard Worker v => { 616*9860b763SAndroid Build Coastguard Worker return Err(km_err!( 617*9860b763SAndroid Build Coastguard Worker InvalidMacLength, 618*9860b763SAndroid Build Coastguard Worker "want 12-16 byte tag for AES-GCM not {} bytes", 619*9860b763SAndroid Build Coastguard Worker v 620*9860b763SAndroid Build Coastguard Worker )) 621*9860b763SAndroid Build Coastguard Worker } 622*9860b763SAndroid Build Coastguard Worker }; 623*9860b763SAndroid Build Coastguard Worker 624*9860b763SAndroid Build Coastguard Worker // Decrypt the encrypted key to be imported, using the ASN.1 DER (re-)encoding of the key 625*9860b763SAndroid Build Coastguard Worker // description as the AAD. 626*9860b763SAndroid Build Coastguard Worker let mut op = self.imp.aes.begin_aead( 627*9860b763SAndroid Build Coastguard Worker OpaqueOr::Explicit(aes_transport_key), 628*9860b763SAndroid Build Coastguard Worker gcm_mode, 629*9860b763SAndroid Build Coastguard Worker crypto::SymmetricOperation::Decrypt, 630*9860b763SAndroid Build Coastguard Worker )?; 631*9860b763SAndroid Build Coastguard Worker op.update_aad( 632*9860b763SAndroid Build Coastguard Worker &cert::asn1_der_encode(&secure_key_wrapper.key_description) 633*9860b763SAndroid Build Coastguard Worker .map_err(|e| der_err!(e, "failed to re-encode SecureKeyWrapper"))?, 634*9860b763SAndroid Build Coastguard Worker )?; 635*9860b763SAndroid Build Coastguard Worker 636*9860b763SAndroid Build Coastguard Worker let mut imported_key_data = op.update(secure_key_wrapper.encrypted_key)?; 637*9860b763SAndroid Build Coastguard Worker imported_key_data.try_extend_from_slice(&op.update(secure_key_wrapper.tag)?)?; 638*9860b763SAndroid Build Coastguard Worker imported_key_data.try_extend_from_slice(&op.finish()?)?; 639*9860b763SAndroid Build Coastguard Worker 640*9860b763SAndroid Build Coastguard Worker // The `Cow::to_mut()` call will not clone, because `from_der()` invokes 641*9860b763SAndroid Build Coastguard Worker // `AuthorizationList::decode_value()` which creates the owned variant. 642*9860b763SAndroid Build Coastguard Worker let imported_key_params: &mut Vec<KeyParam> = 643*9860b763SAndroid Build Coastguard Worker secure_key_wrapper.key_description.key_params.auths.to_mut(); 644*9860b763SAndroid Build Coastguard Worker if let Some(secure_id) = get_opt_tag_value!(&*imported_key_params, UserSecureId)? { 645*9860b763SAndroid Build Coastguard Worker let secure_id = *secure_id; 646*9860b763SAndroid Build Coastguard Worker // If both the Password and Fingerprint bits are set in UserSecureId, the password SID 647*9860b763SAndroid Build Coastguard Worker // should be used, because biometric auth tokens contain both password and fingerprint 648*9860b763SAndroid Build Coastguard Worker // SIDs, but password auth tokens only contain the password SID. 649*9860b763SAndroid Build Coastguard Worker if (secure_id & (HardwareAuthenticatorType::Password as u64) 650*9860b763SAndroid Build Coastguard Worker == (HardwareAuthenticatorType::Password as u64)) 651*9860b763SAndroid Build Coastguard Worker && (secure_id & (HardwareAuthenticatorType::Fingerprint as u64) 652*9860b763SAndroid Build Coastguard Worker == (HardwareAuthenticatorType::Fingerprint as u64)) 653*9860b763SAndroid Build Coastguard Worker { 654*9860b763SAndroid Build Coastguard Worker imported_key_params 655*9860b763SAndroid Build Coastguard Worker .retain(|key_param| !matches!(key_param, KeyParam::UserSecureId(_))); 656*9860b763SAndroid Build Coastguard Worker imported_key_params.try_push(KeyParam::UserSecureId(password_sid as u64))?; 657*9860b763SAndroid Build Coastguard Worker } else if secure_id & (HardwareAuthenticatorType::Password as u64) 658*9860b763SAndroid Build Coastguard Worker == (HardwareAuthenticatorType::Password as u64) 659*9860b763SAndroid Build Coastguard Worker { 660*9860b763SAndroid Build Coastguard Worker imported_key_params 661*9860b763SAndroid Build Coastguard Worker .retain(|key_param| !matches!(key_param, KeyParam::UserSecureId(_))); 662*9860b763SAndroid Build Coastguard Worker imported_key_params.try_push(KeyParam::UserSecureId(password_sid as u64))?; 663*9860b763SAndroid Build Coastguard Worker } else if secure_id & (HardwareAuthenticatorType::Fingerprint as u64) 664*9860b763SAndroid Build Coastguard Worker == (HardwareAuthenticatorType::Fingerprint as u64) 665*9860b763SAndroid Build Coastguard Worker { 666*9860b763SAndroid Build Coastguard Worker imported_key_params 667*9860b763SAndroid Build Coastguard Worker .retain(|key_param| !matches!(key_param, KeyParam::UserSecureId(_))); 668*9860b763SAndroid Build Coastguard Worker imported_key_params.try_push(KeyParam::UserSecureId(biometric_sid as u64))?; 669*9860b763SAndroid Build Coastguard Worker } 670*9860b763SAndroid Build Coastguard Worker }; 671*9860b763SAndroid Build Coastguard Worker 672*9860b763SAndroid Build Coastguard Worker // There is no way for clients to pass CERTIFICATE_NOT_BEFORE and CERTIFICATE_NOT_AFTER. 673*9860b763SAndroid Build Coastguard Worker // importWrappedKey must use validity with no well-defined expiration date. 674*9860b763SAndroid Build Coastguard Worker imported_key_params.try_push(KeyParam::CertificateNotBefore(UNDEFINED_NOT_BEFORE))?; 675*9860b763SAndroid Build Coastguard Worker imported_key_params.try_push(KeyParam::CertificateNotAfter(UNDEFINED_NOT_AFTER))?; 676*9860b763SAndroid Build Coastguard Worker 677*9860b763SAndroid Build Coastguard Worker self.import_key( 678*9860b763SAndroid Build Coastguard Worker imported_key_params, 679*9860b763SAndroid Build Coastguard Worker KeyFormat::try_from(secure_key_wrapper.key_description.key_format).map_err(|_e| { 680*9860b763SAndroid Build Coastguard Worker km_err!( 681*9860b763SAndroid Build Coastguard Worker UnsupportedKeyFormat, 682*9860b763SAndroid Build Coastguard Worker "could not convert the provided keyformat {}", 683*9860b763SAndroid Build Coastguard Worker secure_key_wrapper.key_description.key_format 684*9860b763SAndroid Build Coastguard Worker ) 685*9860b763SAndroid Build Coastguard Worker })?, 686*9860b763SAndroid Build Coastguard Worker &imported_key_data, 687*9860b763SAndroid Build Coastguard Worker None, 688*9860b763SAndroid Build Coastguard Worker KeyImport::Wrapped, 689*9860b763SAndroid Build Coastguard Worker ) 690*9860b763SAndroid Build Coastguard Worker } 691*9860b763SAndroid Build Coastguard Worker upgrade_key( &mut self, keyblob_to_upgrade: &[u8], upgrade_params: Vec<KeyParam>, ) -> Result<Vec<u8>, Error>692*9860b763SAndroid Build Coastguard Worker pub(crate) fn upgrade_key( 693*9860b763SAndroid Build Coastguard Worker &mut self, 694*9860b763SAndroid Build Coastguard Worker keyblob_to_upgrade: &[u8], 695*9860b763SAndroid Build Coastguard Worker upgrade_params: Vec<KeyParam>, 696*9860b763SAndroid Build Coastguard Worker ) -> Result<Vec<u8>, Error> { 697*9860b763SAndroid Build Coastguard Worker let (mut keyblob, mut modified) = 698*9860b763SAndroid Build Coastguard Worker match self.keyblob_parse_decrypt_backlevel(keyblob_to_upgrade, &upgrade_params) { 699*9860b763SAndroid Build Coastguard Worker Ok(v) => (v.0, false), 700*9860b763SAndroid Build Coastguard Worker Err(Error::Hal(ErrorCode::KeyRequiresUpgrade, _)) => { 701*9860b763SAndroid Build Coastguard Worker // Because `keyblob_parse_decrypt_backlevel` explicitly allows back-level 702*9860b763SAndroid Build Coastguard Worker // versioned keys, a `KeyRequiresUpgrade` error indicates that the keyblob looks 703*9860b763SAndroid Build Coastguard Worker // to be in legacy format. Try to convert it. 704*9860b763SAndroid Build Coastguard Worker let legacy_handler = 705*9860b763SAndroid Build Coastguard Worker self.dev.legacy_key.as_mut().ok_or_else(|| { 706*9860b763SAndroid Build Coastguard Worker km_err!(KeymintNotConfigured, "no legacy key handler") 707*9860b763SAndroid Build Coastguard Worker })?; 708*9860b763SAndroid Build Coastguard Worker ( 709*9860b763SAndroid Build Coastguard Worker legacy_handler.convert_legacy_key( 710*9860b763SAndroid Build Coastguard Worker keyblob_to_upgrade, 711*9860b763SAndroid Build Coastguard Worker &upgrade_params, 712*9860b763SAndroid Build Coastguard Worker self.boot_info 713*9860b763SAndroid Build Coastguard Worker .as_ref() 714*9860b763SAndroid Build Coastguard Worker .ok_or_else(|| km_err!(HardwareNotYetAvailable, "no boot info"))?, 715*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 716*9860b763SAndroid Build Coastguard Worker )?, 717*9860b763SAndroid Build Coastguard Worker // Force the emission of a new keyblob even if versions are the same. 718*9860b763SAndroid Build Coastguard Worker true, 719*9860b763SAndroid Build Coastguard Worker ) 720*9860b763SAndroid Build Coastguard Worker } 721*9860b763SAndroid Build Coastguard Worker Err(e) => return Err(e), 722*9860b763SAndroid Build Coastguard Worker }; 723*9860b763SAndroid Build Coastguard Worker 724*9860b763SAndroid Build Coastguard Worker fn upgrade(v: &mut u32, curr: u32, name: &str) -> Result<bool, Error> { 725*9860b763SAndroid Build Coastguard Worker match (*v).cmp(&curr) { 726*9860b763SAndroid Build Coastguard Worker Ordering::Less => { 727*9860b763SAndroid Build Coastguard Worker *v = curr; 728*9860b763SAndroid Build Coastguard Worker Ok(true) 729*9860b763SAndroid Build Coastguard Worker } 730*9860b763SAndroid Build Coastguard Worker Ordering::Equal => Ok(false), 731*9860b763SAndroid Build Coastguard Worker Ordering::Greater => { 732*9860b763SAndroid Build Coastguard Worker error!("refusing to downgrade {} from {} to {}", name, v, curr); 733*9860b763SAndroid Build Coastguard Worker Err(km_err!( 734*9860b763SAndroid Build Coastguard Worker InvalidArgument, 735*9860b763SAndroid Build Coastguard Worker "keyblob with future {} {} (current {})", 736*9860b763SAndroid Build Coastguard Worker name, 737*9860b763SAndroid Build Coastguard Worker v, 738*9860b763SAndroid Build Coastguard Worker curr 739*9860b763SAndroid Build Coastguard Worker )) 740*9860b763SAndroid Build Coastguard Worker } 741*9860b763SAndroid Build Coastguard Worker } 742*9860b763SAndroid Build Coastguard Worker } 743*9860b763SAndroid Build Coastguard Worker 744*9860b763SAndroid Build Coastguard Worker for chars in &mut keyblob.characteristics { 745*9860b763SAndroid Build Coastguard Worker if chars.security_level != self.hw_info.security_level { 746*9860b763SAndroid Build Coastguard Worker continue; 747*9860b763SAndroid Build Coastguard Worker } 748*9860b763SAndroid Build Coastguard Worker for param in &mut chars.authorizations { 749*9860b763SAndroid Build Coastguard Worker match param { 750*9860b763SAndroid Build Coastguard Worker KeyParam::OsVersion(v) => { 751*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info { 752*9860b763SAndroid Build Coastguard Worker if hal_info.os_version == 0 { 753*9860b763SAndroid Build Coastguard Worker // Special case: upgrades to OS version zero are always allowed. 754*9860b763SAndroid Build Coastguard Worker warn!("forcing upgrade to OS version 0"); 755*9860b763SAndroid Build Coastguard Worker modified |= *v != 0; 756*9860b763SAndroid Build Coastguard Worker *v = 0; 757*9860b763SAndroid Build Coastguard Worker } else { 758*9860b763SAndroid Build Coastguard Worker modified |= upgrade(v, hal_info.os_version, "OS version")?; 759*9860b763SAndroid Build Coastguard Worker } 760*9860b763SAndroid Build Coastguard Worker } else { 761*9860b763SAndroid Build Coastguard Worker error!("OS version not available, can't upgrade from {}", v); 762*9860b763SAndroid Build Coastguard Worker } 763*9860b763SAndroid Build Coastguard Worker } 764*9860b763SAndroid Build Coastguard Worker KeyParam::OsPatchlevel(v) => { 765*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info { 766*9860b763SAndroid Build Coastguard Worker modified |= upgrade(v, hal_info.os_patchlevel, "OS patchlevel")?; 767*9860b763SAndroid Build Coastguard Worker } else { 768*9860b763SAndroid Build Coastguard Worker error!("OS patchlevel not available, can't upgrade from {}", v); 769*9860b763SAndroid Build Coastguard Worker } 770*9860b763SAndroid Build Coastguard Worker } 771*9860b763SAndroid Build Coastguard Worker KeyParam::VendorPatchlevel(v) => { 772*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info { 773*9860b763SAndroid Build Coastguard Worker modified |= 774*9860b763SAndroid Build Coastguard Worker upgrade(v, hal_info.vendor_patchlevel, "vendor patchlevel")?; 775*9860b763SAndroid Build Coastguard Worker } else { 776*9860b763SAndroid Build Coastguard Worker error!("vendor patchlevel not available, can't upgrade from {}", v); 777*9860b763SAndroid Build Coastguard Worker } 778*9860b763SAndroid Build Coastguard Worker } 779*9860b763SAndroid Build Coastguard Worker KeyParam::BootPatchlevel(v) => { 780*9860b763SAndroid Build Coastguard Worker if let Some(boot_info) = &self.boot_info { 781*9860b763SAndroid Build Coastguard Worker modified |= upgrade(v, boot_info.boot_patchlevel, "boot patchlevel")?; 782*9860b763SAndroid Build Coastguard Worker } else { 783*9860b763SAndroid Build Coastguard Worker error!("boot patchlevel not available, can't upgrade from {}", v); 784*9860b763SAndroid Build Coastguard Worker } 785*9860b763SAndroid Build Coastguard Worker } 786*9860b763SAndroid Build Coastguard Worker _ => {} 787*9860b763SAndroid Build Coastguard Worker } 788*9860b763SAndroid Build Coastguard Worker } 789*9860b763SAndroid Build Coastguard Worker } 790*9860b763SAndroid Build Coastguard Worker 791*9860b763SAndroid Build Coastguard Worker if !modified { 792*9860b763SAndroid Build Coastguard Worker // No upgrade needed, return empty data to indicate existing keyblob can still be used. 793*9860b763SAndroid Build Coastguard Worker return Ok(Vec::new()); 794*9860b763SAndroid Build Coastguard Worker } 795*9860b763SAndroid Build Coastguard Worker 796*9860b763SAndroid Build Coastguard Worker // Now re-build the keyblob. Use a potentially fresh key encryption key, and potentially a 797*9860b763SAndroid Build Coastguard Worker // new secure deletion secret slot. (The old slot will be released when Keystore performs 798*9860b763SAndroid Build Coastguard Worker // the corresponding `deleteKey` operation on the old keyblob. 799*9860b763SAndroid Build Coastguard Worker let kek_context = self.dev.keys.kek_context()?; 800*9860b763SAndroid Build Coastguard Worker let root_kek = self.root_kek(&kek_context)?; 801*9860b763SAndroid Build Coastguard Worker let hidden = tag::hidden(&upgrade_params, self.root_of_trust()?)?; 802*9860b763SAndroid Build Coastguard Worker let encrypted_keyblob = keyblob::encrypt( 803*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level, 804*9860b763SAndroid Build Coastguard Worker match &mut self.dev.sdd_mgr { 805*9860b763SAndroid Build Coastguard Worker None => None, 806*9860b763SAndroid Build Coastguard Worker Some(mr) => Some(&mut **mr), 807*9860b763SAndroid Build Coastguard Worker }, 808*9860b763SAndroid Build Coastguard Worker &*self.imp.aes, 809*9860b763SAndroid Build Coastguard Worker &*self.imp.hkdf, 810*9860b763SAndroid Build Coastguard Worker &mut *self.imp.rng, 811*9860b763SAndroid Build Coastguard Worker &root_kek, 812*9860b763SAndroid Build Coastguard Worker &kek_context, 813*9860b763SAndroid Build Coastguard Worker keyblob, 814*9860b763SAndroid Build Coastguard Worker hidden, 815*9860b763SAndroid Build Coastguard Worker keyblob::SlotPurpose::KeyUpgrade, 816*9860b763SAndroid Build Coastguard Worker )?; 817*9860b763SAndroid Build Coastguard Worker Ok(encrypted_keyblob.into_vec()?) 818*9860b763SAndroid Build Coastguard Worker } 819*9860b763SAndroid Build Coastguard Worker } 820