diff --git a/src/lib.rs b/src/lib.rs index 5e7b157..1c02065 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -487,11 +487,16 @@ pub trait Tpm { exported_key: &LoadableMachineKey, ) -> Result; - fn hmac_key_create(&mut self, mk: &MachineKey) -> Result; + fn hmac_key_create( + &mut self, + mk: &MachineKey, + auth_value: Option<&AuthValue>, + ) -> Result; fn hmac_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, exported_key: &LoadableHmacKey, ) -> Result; @@ -500,12 +505,14 @@ pub trait Tpm { fn identity_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, algorithm: KeyAlgorithm, ) -> Result; fn identity_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, ) -> Result; @@ -523,6 +530,7 @@ pub trait Tpm { fn identity_key_certificate_request( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, cn: &str, ) -> Result, TpmError>; @@ -530,6 +538,7 @@ pub trait Tpm { fn identity_key_associate_certificate( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, certificate_der: &[u8], ) -> Result; @@ -546,6 +555,7 @@ pub trait Tpm { fn msoapxbc_rsa_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, ) -> Result; #[cfg(feature = "msextensions")] @@ -559,6 +569,7 @@ pub trait Tpm { fn msoapxbc_rsa_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableMsOapxbcRsaKey, ) -> Result; @@ -619,16 +630,21 @@ impl Tpm for BoxedDynTpm { self.0.machine_key_load(auth_value, exported_key) } - fn hmac_key_create(&mut self, mk: &MachineKey) -> Result { - self.0.hmac_key_create(mk) + fn hmac_key_create( + &mut self, + mk: &MachineKey, + auth_value: Option<&AuthValue>, + ) -> Result { + self.0.hmac_key_create(mk, auth_value) } fn hmac_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, exported_key: &LoadableHmacKey, ) -> Result { - self.0.hmac_key_load(mk, exported_key) + self.0.hmac_key_load(mk, auth_value, exported_key) } fn hmac(&mut self, hk: &HmacKey, input: &[u8]) -> Result, TpmError> { @@ -638,17 +654,19 @@ impl Tpm for BoxedDynTpm { fn identity_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, algorithm: KeyAlgorithm, ) -> Result { - self.0.identity_key_create(mk, algorithm) + self.0.identity_key_create(mk, auth_value, algorithm) } fn identity_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, ) -> Result { - self.0.identity_key_load(mk, loadable_key) + self.0.identity_key_load(mk, auth_value, loadable_key) } fn identity_key_id(&mut self, key: &IdentityKey) -> Result, TpmError> { @@ -671,21 +689,23 @@ impl Tpm for BoxedDynTpm { fn identity_key_certificate_request( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, cn: &str, ) -> Result, TpmError> { self.0 - .identity_key_certificate_request(mk, loadable_key, cn) + .identity_key_certificate_request(mk, auth_value, loadable_key, cn) } fn identity_key_associate_certificate( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, certificate_der: &[u8], ) -> Result { self.0 - .identity_key_associate_certificate(mk, loadable_key, certificate_der) + .identity_key_associate_certificate(mk, auth_value, loadable_key, certificate_der) } fn identity_key_public_as_der(&mut self, key: &IdentityKey) -> Result, TpmError> { @@ -708,8 +728,9 @@ impl Tpm for BoxedDynTpm { fn msoapxbc_rsa_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, ) -> Result { - self.0.msoapxbc_rsa_key_create(mk) + self.0.msoapxbc_rsa_key_create(mk, auth_value) } #[cfg(feature = "msextensions")] @@ -725,9 +746,10 @@ impl Tpm for BoxedDynTpm { fn msoapxbc_rsa_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableMsOapxbcRsaKey, ) -> Result { - self.0.msoapxbc_rsa_key_load(mk, loadable_key) + self.0.msoapxbc_rsa_key_load(mk, auth_value, loadable_key) } #[cfg(feature = "msextensions")] @@ -810,15 +832,18 @@ mod tests { .machine_key_load(&auth_value, &loadable_machine_key) .expect("Unable to load machine key"); + let hmac_auth_value = + AuthValue::ephemeral().expect("Failed to generate new random secret"); + // from that ctx, create a hmac key. let loadable_hmac_key = $tpm_a - .hmac_key_create(&machine_key) + .hmac_key_create(&machine_key, Some(&hmac_auth_value)) .expect("Unable to create new hmac key"); trace!(?loadable_hmac_key); let hmac_key = $tpm_a - .hmac_key_load(&machine_key, &loadable_hmac_key) + .hmac_key_load(&machine_key, Some(&hmac_auth_value), &loadable_hmac_key) .expect("Unable to load hmac key"); // do a hmac. @@ -838,7 +863,7 @@ mod tests { // Load the keys. let hmac_key = $tpm_b - .hmac_key_load(&machine_key, &loadable_hmac_key) + .hmac_key_load(&machine_key, Some(&hmac_auth_value), &loadable_hmac_key) .expect("Unable to load hmac key"); // Do another hmac @@ -885,15 +910,20 @@ mod tests { .machine_key_load(&auth_value, &loadable_machine_key) .expect("Unable to load machine key"); + let id_key_auth_str = AuthValue::generate().expect("Failed to create hex pin"); + + let id_key_auth_value = + AuthValue::from_str(&id_key_auth_str).expect("Unable to create auth value"); + // from that ctx, create an identity key let loadable_id_key = $tpm - .identity_key_create(&machine_key, $alg) + .identity_key_create(&machine_key, Some(&id_key_auth_value), $alg) .expect("Unable to create id key"); trace!(?loadable_id_key); let id_key = $tpm - .identity_key_load(&machine_key, &loadable_id_key) + .identity_key_load(&machine_key, Some(&id_key_auth_value), &loadable_id_key) .expect("Unable to load id key"); let id_key_public_pem = $tpm @@ -965,9 +995,11 @@ mod tests { .machine_key_load(&auth_value, &loadable_machine_key) .expect("Unable to load machine key"); + let id_key_auth_value = AuthValue::ephemeral().expect("Unable to create auth value"); + // from that ctx, create an identity key let loadable_id_key = $tpm - .identity_key_create(&machine_key, $alg) + .identity_key_create(&machine_key, Some(&id_key_auth_value), $alg) .expect("Unable to create id key"); trace!(?loadable_id_key); @@ -975,7 +1007,12 @@ mod tests { // Get the CSR let csr_der = $tpm - .identity_key_certificate_request(&machine_key, &loadable_id_key, "common name") + .identity_key_certificate_request( + &machine_key, + Some(&id_key_auth_value), + &loadable_id_key, + "common name", + ) .expect("Failed to create csr"); // Now, we need to sign this to an x509 cert externally. @@ -992,6 +1029,7 @@ mod tests { let loadable_id_key = $tpm .identity_key_associate_certificate( &machine_key, + Some(&id_key_auth_value), &loadable_id_key, &signed_cert_der, ) @@ -999,7 +1037,7 @@ mod tests { // Now load it in: let id_key = $tpm - .identity_key_load(&machine_key, &loadable_id_key) + .identity_key_load(&machine_key, Some(&id_key_auth_value), &loadable_id_key) .expect("Unable to load id key"); let id_key_x509_pem = $tpm @@ -1147,13 +1185,20 @@ mod ms_extn_tests { .machine_key_load(&auth_value, &loadable_machine_key) .expect("Unable to load machine key"); + let ms_rsa_key_auth_value = + AuthValue::ephemeral().expect("Failed to generate new random secret"); + // from that ctx, create a hmac key. let loadable_ms_rsa_key = $tpm_a - .msoapxbc_rsa_key_create(&machine_key) + .msoapxbc_rsa_key_create(&machine_key, Some(&ms_rsa_key_auth_value)) .expect("Unable to create new hmac key"); let ms_rsa_key = $tpm_a - .msoapxbc_rsa_key_load(&machine_key, &loadable_ms_rsa_key) + .msoapxbc_rsa_key_load( + &machine_key, + Some(&ms_rsa_key_auth_value), + &loadable_ms_rsa_key, + ) .expect("Unable to load ms rsa key"); // Get the public key as DER diff --git a/src/soft.rs b/src/soft.rs index c058b58..27b41c1 100644 --- a/src/soft.rs +++ b/src/soft.rs @@ -75,7 +75,14 @@ impl Tpm for SoftTpm { } } - fn hmac_key_create(&mut self, mk: &MachineKey) -> Result { + fn hmac_key_create( + &mut self, + mk: &MachineKey, + auth_value: Option<&AuthValue>, + ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } let mut buf = Zeroizing::new([0; HMAC_KEY_LEN]); rand_bytes(buf.as_mut()).map_err(|ossl_err| { error!(?ossl_err); @@ -101,8 +108,12 @@ impl Tpm for SoftTpm { fn hmac_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableHmacKey, ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } match (mk, loadable_key) { ( MachineKey::SoftAes256Gcm { key: mk_key }, @@ -147,8 +158,12 @@ impl Tpm for SoftTpm { fn identity_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, algorithm: KeyAlgorithm, ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } match algorithm { KeyAlgorithm::Ecdsa256 => { let ecgroup = @@ -224,8 +239,12 @@ impl Tpm for SoftTpm { fn identity_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } match (mk, loadable_key) { ( MachineKey::SoftAes256Gcm { key: mk_key }, @@ -457,10 +476,11 @@ impl Tpm for SoftTpm { fn identity_key_certificate_request( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, cn: &str, ) -> Result, TpmError> { - let id_key = self.identity_key_load(mk, loadable_key)?; + let id_key = self.identity_key_load(mk, auth_value, loadable_key)?; let mut req_builder = X509ReqBuilder::new().map_err(|ossl_err| { error!(?ossl_err); @@ -516,10 +536,11 @@ impl Tpm for SoftTpm { fn identity_key_associate_certificate( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, certificate_der: &[u8], ) -> Result { - let id_key = self.identity_key_load(mk, loadable_key)?; + let id_key = self.identity_key_load(mk, auth_value, loadable_key)?; // Verify the certificate matches our key let certificate = X509::from_der(certificate_der).map_err(|ossl_err| { @@ -567,7 +588,12 @@ impl Tpm for SoftTpm { fn msoapxbc_rsa_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } + let rsa = Rsa::generate(2048).map_err(|ossl_err| { error!(?ossl_err); TpmError::RsaGenerate @@ -621,8 +647,12 @@ impl Tpm for SoftTpm { fn msoapxbc_rsa_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableMsOapxbcRsaKey, ) -> Result { + if auth_value.is_some() { + return Err(TpmError::TpmOperationUnsupported); + } match (mk, loadable_key) { ( MachineKey::SoftAes256Gcm { key: mk_key }, diff --git a/src/tpm.rs b/src/tpm.rs index 14678cd..4d1160a 100644 --- a/src/tpm.rs +++ b/src/tpm.rs @@ -230,12 +230,34 @@ impl TpmTss { parent_context: TpmsContext, private: Private, public: Public, + auth_value: Option<&AuthValue>, ) -> Result { + let tpm_auth_value = match auth_value { + Some(auth_value) => Some( + match auth_value { + AuthValue::Key256Bit { auth_key } => Auth::from_bytes(auth_key.as_ref()), + } + .map_err(|tpm_err| { + error!(?tpm_err); + TpmError::TpmAuthValueInvalid + })?, + ), + None => None, + }; // Load our private/public under our parent context, and immediately // flush the parent handle from the context. let key_handle = self.execute_with_temporary_object_context( parent_context, |hsm_ctx, parent_key_handle| { + if let Some(auth_value) = tpm_auth_value { + hsm_ctx + .tpm_ctx + .tr_set_auth(parent_key_handle.into(), auth_value.clone()) + .map_err(|tpm_err| { + error!(?tpm_err); + TpmError::TpmMachineKeyLoad + })?; + } hsm_ctx .tpm_ctx .load(parent_key_handle.into(), private, public) @@ -541,7 +563,23 @@ impl Tpm for TpmTss { } } - fn hmac_key_create(&mut self, mk: &MachineKey) -> Result { + fn hmac_key_create( + &mut self, + mk: &MachineKey, + auth_value: Option<&AuthValue>, + ) -> Result { + let tpm_auth_value = match auth_value { + Some(auth_value) => Some( + match auth_value { + AuthValue::Key256Bit { auth_key } => Auth::from_bytes(auth_key.as_ref()), + } + .map_err(|tpm_err| { + error!(?tpm_err); + TpmError::TpmAuthValueInvalid + })?, + ), + None => None, + }; let mk_key_context = match mk { MachineKey::Tpm { key_context } => key_context.clone(), _ => return Err(TpmError::IncorrectKeyType), @@ -586,7 +624,14 @@ impl Tpm for TpmTss { self.execute_with_temporary_object_context(mk_key_context, |hsm_ctx, mk_key_handle| { hsm_ctx .tpm_ctx - .create(mk_key_handle.into(), key_pub, None, None, None, None) + .create( + mk_key_handle.into(), + key_pub, + tpm_auth_value, + None, + None, + None, + ) .map( |CreateKeyResult { out_private: private, @@ -606,6 +651,7 @@ impl Tpm for TpmTss { fn hmac_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableHmacKey, ) -> Result { let (private, public) = match loadable_key { @@ -618,7 +664,7 @@ impl Tpm for TpmTss { _ => return Err(TpmError::IncorrectKeyType), }; - self.execute_key_load_to_context(mk_key_context, private, public) + self.execute_key_load_to_context(mk_key_context, private, public, auth_value) .map(|key_context| HmacKey::TpmSha256 { key_context }) } @@ -648,8 +694,21 @@ impl Tpm for TpmTss { fn identity_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, algorithm: KeyAlgorithm, ) -> Result { + let tpm_auth_value = match auth_value { + Some(auth_value) => Some( + match auth_value { + AuthValue::Key256Bit { auth_key } => Auth::from_bytes(auth_key.as_ref()), + } + .map_err(|tpm_err| { + error!(?tpm_err); + TpmError::TpmAuthValueInvalid + })?, + ), + None => None, + }; let mk_key_context = match mk { MachineKey::Tpm { key_context } => key_context.clone(), _ => return Err(TpmError::IncorrectKeyType), @@ -721,7 +780,14 @@ impl Tpm for TpmTss { self.execute_with_temporary_object_context(mk_key_context, |hsm_ctx, mk_key_handle| { hsm_ctx .tpm_ctx - .create(mk_key_handle.into(), key_pub, None, None, None, None) + .create( + mk_key_handle.into(), + key_pub, + tpm_auth_value, + None, + None, + None, + ) .map( |CreateKeyResult { out_private: private, @@ -754,6 +820,7 @@ impl Tpm for TpmTss { fn identity_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableIdentityKey, ) -> Result { let (private, public, algorithm, x509) = match loadable_key { @@ -808,7 +875,7 @@ impl Tpm for TpmTss { _ => return Err(TpmError::IncorrectKeyType), }; - self.execute_key_load_to_context(mk_key_context, private, public) + self.execute_key_load_to_context(mk_key_context, private, public, auth_value) .map(|key_context| match algorithm { KeyAlgorithm::Ecdsa256 => IdentityKey::TpmEcdsa256 { key_context, x509 }, KeyAlgorithm::Rsa2048 => IdentityKey::TpmRsa2048 { key_context, x509 }, @@ -1020,6 +1087,7 @@ impl Tpm for TpmTss { fn identity_key_certificate_request( &mut self, _mk: &MachineKey, + _auth_value: Option<&AuthValue>, _loadable_key: &LoadableIdentityKey, _cn: &str, ) -> Result, TpmError> { @@ -1029,6 +1097,7 @@ impl Tpm for TpmTss { fn identity_key_associate_certificate( &mut self, _mk: &MachineKey, + _auth_value: Option<&AuthValue>, _loadable_key: &LoadableIdentityKey, _certificate_der: &[u8], ) -> Result { @@ -1071,7 +1140,21 @@ impl Tpm for TpmTss { fn msoapxbc_rsa_key_create( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, ) -> Result { + let tpm_auth_value = match auth_value { + Some(auth_value) => Some( + match auth_value { + AuthValue::Key256Bit { auth_key } => Auth::from_bytes(auth_key.as_ref()), + } + .map_err(|tpm_err| { + error!(?tpm_err); + TpmError::TpmAuthValueInvalid + })?, + ), + None => None, + }; + let mk_key_context = match mk { MachineKey::Tpm { key_context } => key_context.clone(), _ => return Err(TpmError::IncorrectKeyType), @@ -1121,7 +1204,14 @@ impl Tpm for TpmTss { |hsm_ctx, mk_key_handle| { hsm_ctx .tpm_ctx - .create(mk_key_handle.into(), key_pub, None, None, None, None) + .create( + mk_key_handle.into(), + key_pub, + tpm_auth_value, + None, + None, + None, + ) .map( |CreateKeyResult { out_private: private, @@ -1180,6 +1270,7 @@ impl Tpm for TpmTss { fn msoapxbc_rsa_key_load( &mut self, mk: &MachineKey, + auth_value: Option<&AuthValue>, loadable_key: &LoadableMsOapxbcRsaKey, ) -> Result { let (private, public, cek_private, cek_public) = match loadable_key { @@ -1202,12 +1293,16 @@ impl Tpm for TpmTss { _ => return Err(TpmError::IncorrectKeyType), }; - let cek_context = - self.execute_key_load_to_context(mk_key_context.clone(), cek_private, cek_public)?; + let cek_context = self.execute_key_load_to_context( + mk_key_context.clone(), + cek_private, + cek_public, + auth_value, + )?; tracing::trace!("cek context created"); - self.execute_key_load_to_context(mk_key_context, private, public) + self.execute_key_load_to_context(mk_key_context, private, public, auth_value) .map(|key_context| MsOapxbcRsaKey::Tpm { key_context, cek_context,