diff --git a/Cargo.toml b/Cargo.toml index e88eb84a..d152b1f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,39 @@ [workspace] resolver = "2" members = ["tss-esapi", "tss-esapi-sys"] + +[patch.crates-io] +p192 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } +p224 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } +p256 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } +p384 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } +p521 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } +sm2 = { git = "https://github.com/baloo/elliptic-curves.git", branch = "baloo/group/try-from-rng" } + +# https://github.com/RustCrypto/KDFs/pull/108 +concat-kdf = { git = "https://github.com/RustCrypto/KDFs.git" } + +cfb-mode = { git = "https://github.com/RustCrypto/block-modes.git" } + +# https://github.com/RustCrypto/RSA/pull/467 +rsa = { git = "https://github.com/RustCrypto/RSA.git" } + +crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint.git" } +crypto-primes = { git = "https://github.com/entropyxyz/crypto-primes.git" } + +ecdsa = { git = "https://github.com/RustCrypto/signatures.git" } +rfc6979 = { git = "https://github.com/RustCrypto/signatures.git" } + +x509-cert = { git = "https://github.com/baloo/formats.git", branch = "baloo/reunite-workspace" } + +elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" } +signature = { git = "https://github.com/RustCrypto/traits.git" } +#crypto-common = { git = "https://github.com/RustCrypto/traits.git" } +#digest = { git = "https://github.com/RustCrypto/traits.git" } + +hmac = { git = "https://github.com/RustCrypto/MACs.git" } + +ff = { git = "https://github.com/zkcrypto/ff.git", branch = "release-0.14.0" } +group = { git = "https://github.com/baloo/group.git", branch = "baloo/try_from_rng" } + +aes = { git = "https://github.com/RustCrypto/block-ciphers.git" } diff --git a/tss-esapi/Cargo.toml b/tss-esapi/Cargo.toml index 05375b05..309a4564 100644 --- a/tss-esapi/Cargo.toml +++ b/tss-esapi/Cargo.toml @@ -34,40 +34,50 @@ hostname-validator = "1.1.0" regex = "1.3.9" zeroize = { version = "1.5.7", features = ["zeroize_derive"] } tss-esapi-sys = { path = "../tss-esapi-sys", version = "0.5.0" } -x509-cert = { version = "0.2.0", optional = true } -ecdsa = { version = "0.16.9", features = ["der", "hazmat", "arithmetic", "verifying"], optional = true } -elliptic-curve = { version = "0.13.8", optional = true, features = ["alloc", "pkcs8"] } -p192 = { version = "0.13.0", optional = true } -p224 = { version = "0.13.2", optional = true } -p256 = { version = "0.13.2", optional = true } -p384 = { version = "0.13.0", optional = true } -p521 = { version = "0.13.3", optional = true } -pkcs8 = { version = "0.10.2", optional = true } -rsa = { version = "0.9", optional = true } -sha1 = { version = "0.10.6", optional = true } -sha2 = { version = "0.10.8", optional = true } -sha3 = { version = "0.10.8", optional = true } -sm2 = { version = "0.13.3", optional = true } -sm3 = { version = "0.4.2", optional = true } -digest = { version = "0.10.7", optional = true } -signature = { version = "2.2.0", features = ["std"], optional = true} +x509-cert = { version = "0.3.0-pre.0", optional = true } +aes = { version = "0.9.0-pre.2", optional = true } +cfb-mode = { version = "0.9.0-pre", optional = true } +ecdsa = { version = "0.17.0-pre.9", features = ["der", "hazmat", "arithmetic", "verifying"], optional = true } +elliptic-curve = { version = "0.14.0-rc.1", optional = true, features = ["alloc", "pkcs8"] } +hmac = { version = "0.13.0-pre.4", optional = true } +p192 = { version = "0.14.0-pre", optional = true } +p224 = { version = "0.14.0-pre", optional = true } +p256 = { version = "0.14.0-pre.2", optional = true } +p384 = { version = "0.14.0-pre.2", optional = true } +p521 = { version = "0.14.0-pre.2", optional = true } +pkcs8 = { version = "0.11.0-rc.1", optional = true } +rsa = { version = "0.10.0-pre.4", optional = true } +sha1 = { version = "0.11.0-pre.5", optional = true } +sha2 = { version = "0.11.0-pre.5", optional = true } +sha3 = { version = "0.11.0-pre.5", optional = true } +sm2 = { version = "0.14.0-pre", optional = true } +sm3 = { version = "0.5.0-pre.4", optional = true } +digest = { version = "0.11.0-pre.9", optional = true } +kbkdf = { version = "0.0.1", optional = true } +concat-kdf = { version = "0.2.0-pre", optional = true } +signature = { version = "2.3.0-pre.4", features = ["std"], optional = true} cfg-if = "1.0.0" strum = { version = "0.26.3", optional = true } strum_macros = { version = "0.26.4", optional = true } paste = "1.0.14" -getrandom = "0.2.11" +getrandom = "0.3" +rand = "0.9" [dev-dependencies] +aes = "0.9.0-pre.2" env_logger = "0.11.5" +hex-literal = "0.4.1" +rsa = { version = "0.10.0-pre.3" } serde_json = "^1.0.108" -sha2 = { version = "0.10.8", features = ["oid"] } +sha2 = { version = "0.11.0-pre.4", features = ["oid"] } tss-esapi = { path = ".", features = [ "integration-tests", "serde", "abstraction", "rustcrypto-full", ] } -x509-cert = { version = "0.2.0", features = ["builder"] } +p256 = { version = "0.14.0-pre.2", features = ["ecdh"] } +x509-cert = { version = "0.3.0-pre.0", features = ["builder"] } [build-dependencies] semver = "1.0.7" @@ -78,8 +88,8 @@ generate-bindings = ["tss-esapi-sys/generate-bindings"] abstraction = ["rustcrypto"] integration-tests = ["strum", "strum_macros"] -rustcrypto = ["digest", "ecdsa", "elliptic-curve", "pkcs8", "signature", "x509-cert"] -rustcrypto-full = ["rustcrypto", "p192", "p224", "p256", "p384", "p521", "rsa", "sha1", "sha2", "sha3", "sm2", "sm3"] - +rustcrypto = ["cfb-mode", "concat-kdf", "digest", "ecdsa", "elliptic-curve/ecdh", "pkcs8", "signature", "x509-cert"] +rustcrypto-full = ["rustcrypto", "aes", "p192", "p224", "p256", "p384", "p521", "rsa", "sha1", "sha2", "sha3", "sm2", "sm3"] + sha1 = ["dep:sha1", "rsa?/sha1"] sha2 = ["dep:sha2", "rsa?/sha2"] diff --git a/tss-esapi/src/abstraction/no_tpm/quote.rs b/tss-esapi/src/abstraction/no_tpm/quote.rs index 59733df3..40f0c2f2 100644 --- a/tss-esapi/src/abstraction/no_tpm/quote.rs +++ b/tss-esapi/src/abstraction/no_tpm/quote.rs @@ -13,13 +13,10 @@ use digest::{Digest, DynDigest}; #[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] use crate::{abstraction::public::AssociatedTpmCurve, structures::EccSignature}; #[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] -use ecdsa::{ - hazmat::{DigestPrimitive, VerifyPrimitive}, - PrimeCurve, SignatureSize, VerifyingKey, -}; +use ecdsa::{hazmat::DigestPrimitive, PrimeCurve, SignatureSize, VerifyingKey}; #[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] use elliptic_curve::{ - generic_array::ArrayLength, + array::ArraySize, point::AffinePoint, sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint}, CurveArithmetic, FieldBytesSize, @@ -41,8 +38,8 @@ fn verify_ecdsa( ) -> Result where C: PrimeCurve + CurveArithmetic + DigestPrimitive + AssociatedTpmCurve, - AffinePoint: VerifyPrimitive + FromEncodedPoint + ToEncodedPoint, - SignatureSize: ArrayLength, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + SignatureSize: ArraySize, FieldBytesSize: ModulusSize, { let Ok(signature) = ecdsa::Signature::::try_from(signature.clone()) else { diff --git a/tss-esapi/src/abstraction/public.rs b/tss-esapi/src/abstraction/public.rs index 2f0d5bb7..0d56c6ba 100644 --- a/tss-esapi/src/abstraction/public.rs +++ b/tss-esapi/src/abstraction/public.rs @@ -8,7 +8,7 @@ use crate::{Error, WrapperErrorKind}; use core::convert::TryFrom; use elliptic_curve::{ - generic_array::typenum::Unsigned, + array::typenum::Unsigned, sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint}, AffinePoint, CurveArithmetic, FieldBytesSize, PublicKey, }; @@ -18,7 +18,7 @@ use x509_cert::spki::SubjectPublicKeyInfoOwned; #[cfg(feature = "rsa")] use { crate::structures::RsaExponent, - rsa::{BigUint, RsaPublicKey}, + rsa::{BoxedUint, RsaPublicKey}, }; #[cfg(any( @@ -57,15 +57,13 @@ where let x = unique.x().as_bytes(); let y = unique.y().as_bytes(); - if x.len() != FieldBytesSize::::USIZE { - return Err(Error::local_error(WrapperErrorKind::InvalidParam)); - } - if y.len() != FieldBytesSize::::USIZE { - return Err(Error::local_error(WrapperErrorKind::InvalidParam)); - } - - let encoded_point = - EncodedPoint::::from_affine_coordinates(x.into(), y.into(), false); + let encoded_point = EncodedPoint::::from_affine_coordinates( + x.try_into() + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?, + y.try_into() + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?, + false, + ); let public_key = PublicKey::::try_from(&encoded_point) .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?; @@ -86,10 +84,11 @@ impl TryFrom<&Public> for RsaPublicKey { unique, parameters, .. } => { let exponent = match parameters.exponent() { - RsaExponent::ZERO_EXPONENT => BigUint::from(RSA_DEFAULT_EXP), - _ => BigUint::from(parameters.exponent().value()), + RsaExponent::ZERO_EXPONENT => BoxedUint::from(RSA_DEFAULT_EXP), + _ => BoxedUint::from(parameters.exponent().value()), }; - let modulus = BigUint::from_bytes_be(unique.as_bytes()); + let modulus = BoxedUint::from_be_slice(unique.as_bytes(), 8192) + .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize))?; let public_key = RsaPublicKey::new(modulus, exponent) .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?; @@ -173,8 +172,6 @@ where let x = x.as_slice(); let y = y.as_slice(); - // TODO: When elliptic_curve bumps to 0.14, we can use the TryFrom implementation instead - // of checking lengths manually if x.len() != FieldBytesSize::::USIZE { return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } @@ -182,8 +179,14 @@ where return Err(Error::local_error(WrapperErrorKind::InvalidParam)); } - let encoded_point = - EncodedPoint::::from_affine_coordinates(x.into(), y.into(), false); + let encoded_point = EncodedPoint::::from_affine_coordinates( + x.try_into() + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?, + y.try_into() + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?, + false, + ); + let public_key = PublicKey::::try_from(&encoded_point) .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?; @@ -201,8 +204,9 @@ impl TryFrom<&TpmPublicKey> for RsaPublicKey { fn try_from(value: &TpmPublicKey) -> Result { match value { TpmPublicKey::Rsa(modulus) => { - let exponent = BigUint::from(RSA_DEFAULT_EXP); - let modulus = BigUint::from_bytes_be(modulus.as_slice()); + let exponent = BoxedUint::from(RSA_DEFAULT_EXP); + let modulus = BoxedUint::from_be_slice(modulus.as_slice(), 8192) + .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize))?; let public_key = RsaPublicKey::new(modulus, exponent) .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?; diff --git a/tss-esapi/src/abstraction/signatures.rs b/tss-esapi/src/abstraction/signatures.rs index e4b8a578..ea41f465 100644 --- a/tss-esapi/src/abstraction/signatures.rs +++ b/tss-esapi/src/abstraction/signatures.rs @@ -5,9 +5,9 @@ use crate::{structures::EccSignature, Error, Result, WrapperErrorKind}; use std::convert::TryFrom; -use ecdsa::SignatureSize; +use ecdsa::{EcdsaCurve, SignatureSize}; use elliptic_curve::{ - generic_array::{typenum::Unsigned, ArrayLength}, + array::{typenum::Unsigned, ArraySize}, FieldBytes, FieldBytesSize, PrimeCurve, }; @@ -16,8 +16,8 @@ use crate::structures::Signature; impl TryFrom for ecdsa::Signature where - C: PrimeCurve, - SignatureSize: ArrayLength, + C: PrimeCurve + EcdsaCurve, + SignatureSize: ArraySize, { type Error = Error; @@ -33,8 +33,12 @@ where } let signature = ecdsa::Signature::from_scalars( - FieldBytes::::from_slice(r).clone(), - FieldBytes::::from_slice(s).clone(), + FieldBytes::::try_from(r) + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))? + .clone(), + FieldBytes::::try_from(s) + .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))? + .clone(), ) .map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?; Ok(signature) diff --git a/tss-esapi/src/abstraction/signer.rs b/tss-esapi/src/abstraction/signer.rs index 7689e1a7..9faf6bcd 100644 --- a/tss-esapi/src/abstraction/signer.rs +++ b/tss-esapi/src/abstraction/signer.rs @@ -24,11 +24,11 @@ use std::{convert::TryFrom, ops::Add, sync::Mutex}; use digest::{Digest, FixedOutput, Output}; use ecdsa::{ der::{MaxOverhead, MaxSize, Signature as DerSignature}, - hazmat::{DigestPrimitive, SignPrimitive}, - Signature, SignatureSize, VerifyingKey, + hazmat::DigestPrimitive, + EcdsaCurve, Signature, SignatureSize, VerifyingKey, }; use elliptic_curve::{ - generic_array::ArrayLength, + array::ArraySize, ops::Invert, sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint}, subtle::CtOption, @@ -139,7 +139,7 @@ impl TpmSigner #[derive(Debug)] pub struct EcSigner where - C: PrimeCurve + CurveArithmetic, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, { context: Ctx, verifying_key: VerifyingKey, @@ -147,7 +147,7 @@ where impl EcSigner where - C: PrimeCurve + CurveArithmetic, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, C: AssociatedTpmCurve, FieldBytesSize: ModulusSize, AffinePoint: FromEncodedPoint + ToEncodedPoint, @@ -179,14 +179,14 @@ where impl EcSigner where - C: PrimeCurve + CurveArithmetic, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, C: AssociatedTpmCurve, { /// Key parameters for this curve, selected digest is the one selected by DigestPrimitive pub fn key_params_default() -> KeyParams where C: DigestPrimitive, - ::Digest: FixedOutput>, + ::Digest: FixedOutput, ::Digest: AssociatedHashingAlgorithm, { Self::key_params::<::Digest>() @@ -199,7 +199,7 @@ where /// The hashing algorithm `D` is the digest that will be used for signatures (SHA-256, SHA3-256, ...). pub fn key_params() -> KeyParams where - D: FixedOutput>, + D: FixedOutput, D: AssociatedHashingAlgorithm, { KeyParams::Ecc { @@ -212,9 +212,9 @@ where impl AsRef> for EcSigner where - C: PrimeCurve + CurveArithmetic, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, + Scalar: Invert>>, + SignatureSize: ArraySize, { fn as_ref(&self) -> &VerifyingKey { &self.verifying_key @@ -223,21 +223,21 @@ where impl KeypairRef for EcSigner where - C: PrimeCurve + CurveArithmetic, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, + Scalar: Invert>>, + SignatureSize: ArraySize, { type VerifyingKey = VerifyingKey; } impl DigestSigner> for EcSigner where - C: PrimeCurve + CurveArithmetic, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, C: AssociatedTpmCurve, - D: Digest + FixedOutput>, + D: Digest + FixedOutput, D: AssociatedHashingAlgorithm, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + Scalar: Invert>>, + SignatureSize: ArraySize, TpmDigest: From>, Ctx: TpmSigner, { @@ -261,16 +261,16 @@ where impl DigestSigner> for EcSigner where - C: PrimeCurve + CurveArithmetic, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, C: AssociatedTpmCurve, - D: Digest + FixedOutput>, + D: Digest + FixedOutput, D: AssociatedHashingAlgorithm, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + Scalar: Invert>>, + SignatureSize: ArraySize, TpmDigest: From>, - MaxSize: ArrayLength, - as Add>::Output: Add + ArrayLength, + MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, Ctx: TpmSigner, { @@ -282,11 +282,11 @@ where impl Signer> for EcSigner where - C: PrimeCurve + CurveArithmetic + DigestPrimitive, + C: PrimeCurve + CurveArithmetic + EcdsaCurve + DigestPrimitive, C: AssociatedTpmCurve, ::Digest: AssociatedHashingAlgorithm, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + Scalar: Invert>>, + SignatureSize: ArraySize, TpmDigest: From::Digest>>, Ctx: TpmSigner, @@ -298,15 +298,15 @@ where impl Signer> for EcSigner where - C: PrimeCurve + CurveArithmetic + DigestPrimitive, + C: PrimeCurve + CurveArithmetic + EcdsaCurve + DigestPrimitive, C: AssociatedTpmCurve, ::Digest: AssociatedHashingAlgorithm, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + Scalar: Invert>>, + SignatureSize: ArraySize, TpmDigest: From::Digest>>, - MaxSize: ArrayLength, - as Add>::Output: Add + ArrayLength, + MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, Ctx: TpmSigner, { @@ -317,9 +317,9 @@ where impl SignatureAlgorithmIdentifier for EcSigner where - C: PrimeCurve + CurveArithmetic, - Scalar: Invert>> + SignPrimitive, - SignatureSize: ArrayLength, + C: PrimeCurve + CurveArithmetic + EcdsaCurve, + Scalar: Invert>>, + SignatureSize: ArraySize, Signature: AssociatedAlgorithmIdentifier>, { type Params = AnyRef<'static>; diff --git a/tss-esapi/src/abstraction/transient/mod.rs b/tss-esapi/src/abstraction/transient/mod.rs index 0b9c2d4f..3b43474c 100644 --- a/tss-esapi/src/abstraction/transient/mod.rs +++ b/tss-esapi/src/abstraction/transient/mod.rs @@ -154,7 +154,7 @@ impl TransientKeyContext { let key_auth = if auth_size > 0 { self.set_session_attrs()?; let mut random_bytes = vec![0u8; auth_size]; - getrandom::getrandom(&mut random_bytes).map_err(|_| { + getrandom::fill(&mut random_bytes).map_err(|_| { log::error!("Failed to obtain a random authvalue for key creation"); Error::WrapperError(ErrorKind::InternalError) })?; @@ -674,7 +674,7 @@ impl TransientKeyContextBuilder { let root_key_auth = if self.root_key_auth_size > 0 { let mut random = vec![0u8; self.root_key_auth_size]; - getrandom::getrandom(&mut random).map_err(|_| { + getrandom::fill(&mut random).map_err(|_| { log::error!("Failed to obtain a random value for root key authentication"); Error::WrapperError(ErrorKind::InternalError) })?; diff --git a/tss-esapi/src/structures/buffers.rs b/tss-esapi/src/structures/buffers.rs index 7e6ef094..8734c83f 100644 --- a/tss-esapi/src/structures/buffers.rs +++ b/tss-esapi/src/structures/buffers.rs @@ -225,8 +225,8 @@ pub mod digest { #[cfg(feature = "rustcrypto")] mod rustcrypto { use digest::{ + array::Array, consts::{U20, U32, U48, U64}, - generic_array::GenericArray, typenum::Unsigned, }; @@ -234,15 +234,15 @@ pub mod digest { macro_rules! impl_from_digest { ($($size:ty),+) => { - $(impl From> for Digest { - fn from(mut value: GenericArray) -> Self { + $(impl From> for Digest { + fn from(mut value: Array) -> Self { let value_as_vec = value.as_slice().to_vec(); value.zeroize(); Digest(value_as_vec.into()) } } - impl TryFrom for GenericArray { + impl TryFrom for Array { type Error = Error; fn try_from(value: Digest) -> Result { diff --git a/tss-esapi/src/utils/credential.rs b/tss-esapi/src/utils/credential.rs new file mode 100644 index 00000000..a862d2d3 --- /dev/null +++ b/tss-esapi/src/utils/credential.rs @@ -0,0 +1,284 @@ +// Copyright 2025 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +use core::{ + marker::PhantomData, + ops::{Add, Mul}, +}; + +use cfb_mode::cipher::{AsyncStreamCipher, BlockCipherEncrypt}; +use digest::{ + array::ArraySize, + consts::{B1, U8}, + crypto_common::{Iv, KeyIvInit, KeySizeUser, WeakKeyError}, + typenum::{ + operator_aliases::{Add1, Sum}, + Unsigned, + }, + Digest, DynDigest, FixedOutputReset, Key, KeyInit, Mac, OutputSizeUser, +}; +use ecdsa::elliptic_curve::{ + ecdh::{EphemeralSecret, SharedSecret}, + sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint}, + AffinePoint, Curve, CurveArithmetic, FieldBytesSize, PublicKey, +}; +use hmac::{EagerHash, Hmac}; +use log::error; +use rand::{rng, Rng}; +use rsa::{Oaep, RsaPublicKey}; + +use crate::{ + error::{Error, Result, WrapperErrorKind}, + structures::{EncryptedSecret, IdObject, Name}, + utils::kdf::{self}, +}; + +type WeakResult = core::result::Result; + +// [`TpmHmac`] intends to code for the key expected for hmac +// in the KDFa and KDFe derivations. There are no standard sizes for hmac keys really, +// upstream RustCrypto considers it to be [BlockSize], but TPM specification +// has a different opinion on the matter, and expect the key to the output +// bit size of the hash algorithm used. +// +// See https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=202 +// section 24.5 HMAC: +// bits the number of bits in the digest produced by ekNameAlg +// +// [BlockSize]: https://docs.rs/hmac/0.12.1/hmac/struct.HmacCore.html#impl-KeySizeUser-for-HmacCore%3CD%3E +struct TpmHmac(PhantomData); + +impl KeySizeUser for TpmHmac +where + H: OutputSizeUser, +{ + type KeySize = H::OutputSize; +} + +pub fn make_credential_ecc( + ek_public: PublicKey, + secret: &[u8], + key_name: Name, +) -> Result<(IdObject, EncryptedSecret)> +where + C: Curve + CurveArithmetic, + + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldBytesSize: ModulusSize, + + as Add>::Output: Add>, + Sum, FieldBytesSize>: ArraySize, + Sum, FieldBytesSize>: Add, + Sum, FieldBytesSize>, U8>: Add, + Add1, FieldBytesSize>, U8>>: ArraySize, + + EkHash: Digest + EagerHash + FixedOutputReset, + ::OutputSize: Mul, + <::OutputSize as Mul>::Output: Unsigned, + <::Core as OutputSizeUser>::OutputSize: ArraySize + Mul, + <<::Core as OutputSizeUser>::OutputSize as Mul>::Output: Unsigned, + + EkCipher: KeySizeUser + BlockCipherEncrypt + KeyInit, + ::KeySize: Mul, + <::KeySize as Mul>::Output: ArraySize, +{ + let mut rng = rng(); + + loop { + // See Table 22 - Key Generation for the various labels used here after: + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=183 + + // C.6.4. ECC Secret Sharing for Credentials + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=311 + let local = EphemeralSecret::::random(&mut rng); + + let ecdh_secret: SharedSecret = local.diffie_hellman(&ek_public); + let local_public = local.public_key(); + drop(local); + + let seed = kdf::kdfe::>( + &ecdh_secret, + &local_public, + &ek_public, + )?; + drop(ecdh_secret); + + // The local ECDH pair is used as "encrypted seed" + let encoded_point = local_public.to_encoded_point(false); + let Coordinates::Uncompressed { + x: point_x, + y: point_y, + } = encoded_point.coordinates() + else { + // NOTE: The only way this could trigger would be for the local key to be identity. + error!("Couldn't compute coordinates for the local public key"); + return Err(Error::local_error(WrapperErrorKind::InvalidParam)); + }; + let encrypted_seed = { + let mut out = vec![]; + out.extend_from_slice(&FieldBytesSize::::U16.to_be_bytes()[..]); + out.extend_from_slice(point_x); + out.extend_from_slice(&FieldBytesSize::::U16.to_be_bytes()[..]); + out.extend_from_slice(point_y); + out + }; + let encrypted_secret = EncryptedSecret::from_bytes(&encrypted_seed)?; + + match secret_to_credential::(seed, secret, &key_name)? { + Ok(id_object) => return Ok((id_object, encrypted_secret)), + Err(WeakKeyError) => { + // 11.4.10.4 Rejection of weak keys + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82 + + // The Key was considered weak, and we should re-run the creation of the encrypted + // secret. + continue; + } + } + } +} + +pub fn make_credential_rsa( + ek_public: &RsaPublicKey, + secret: &[u8], + key_name: Name, +) -> Result<(IdObject, EncryptedSecret)> +where + EkHash: Digest + DynDigest + Send + Sync + 'static, + EkHash: EagerHash + FixedOutputReset, + ::OutputSize: Mul, + <::OutputSize as Mul>::Output: Unsigned, + <::Core as OutputSizeUser>::OutputSize: ArraySize + Mul, + <<::Core as OutputSizeUser>::OutputSize as Mul>::Output: Unsigned, + + EkCipher: KeySizeUser + BlockCipherEncrypt + KeyInit, + ::KeySize: Mul, + <::KeySize as Mul>::Output: ArraySize, +{ + let mut rng = rng(); + + loop { + // See Table 22 - Key Generation for the various labels used here after: + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=183 + + // B.10.4 RSA Secret Sharing for Credentials + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=302 + let random_seed = { + let mut out = Key::>::default(); + rng.fill(out.as_mut_slice()); + out + }; + + // The random seed is then encrypted with RSA-OAEP + // + // B.4 RSAES_OAEP + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=297 + // + // The label is a byte-stream whose last byte must be zero + // + // B.10.4. RSA Secret Sharing for Credentials + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=302 + // + // The label is going to be "IDENTITY" for secret sharing. + let encrypted_seed = { + let padding = Oaep::new_with_label::(b"IDENTITY\0".to_vec()); + ek_public + .encrypt(&mut rng, padding, &random_seed[..]) + .map_err(|e| { + error!("RSA OAEP encryption error: {e}"); + Error::local_error(WrapperErrorKind::InternalError) + })? + }; + let encrypted_secret = EncryptedSecret::from_bytes(&encrypted_seed)?; + + match secret_to_credential::(random_seed, secret, &key_name)? { + Ok(id_object) => return Ok((id_object, encrypted_secret)), + Err(WeakKeyError) => { + // 11.4.10.4 Rejection of weak keys + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82 + + // The Key was considered weak, and we should re-run the creation of the encrypted + // secret. + continue; + } + } + } +} + +fn secret_to_credential( + seed: Key>, + secret: &[u8], + key_name: &Name, +) -> Result> +where + EkHash: Digest + EagerHash + FixedOutputReset, + ::OutputSize: Mul, + <::OutputSize as Mul>::Output: Unsigned, + <::Core as OutputSizeUser>::OutputSize: ArraySize + Mul, + <<::Core as OutputSizeUser>::OutputSize as Mul>::Output: Unsigned, + + EkCipher: KeySizeUser + BlockCipherEncrypt + KeyInit, + ::KeySize: Mul, + <::KeySize as Mul>::Output: ArraySize, +{ + // Prepare the sensitive data + // this will be then encrypted using AES-CFB (size of the symmetric key depends on the EK). + // NOTE(security): no need to zeroize it, content is rewritten in place with the encrypted version + let mut sensitive_data = { + let mut out = vec![]; + out.extend_from_slice( + &u16::try_from(secret.len()) + .map_err(|_| { + error!("secret may only be 2^16 bytes long"); + Error::local_error(WrapperErrorKind::WrongParamSize) + })? + .to_be_bytes()[..], + ); + out.extend_from_slice(secret); + out + }; + + // We'll now encrypt the sensitive data, and hmac the result of the encryption + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=201 + // See 24.4 Symmetric Encryption + let sym_key = kdf::kdfa::(&seed, key_name.value(), &[])?; + + if EkCipher::weak_key_test(&sym_key).is_ok() { + // 11.4.10.4 Rejection of weak keys + // https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82 + // The Key was considered weak, and we should re-run the creation of the encrypted + // secret. + + return Ok(Err(WeakKeyError)); + } + + let iv: Iv> = Default::default(); + + cfb_mode::Encryptor::::new(&sym_key, &iv).encrypt(&mut sensitive_data); + + // See 24.5 HMAC + let hmac_key = kdf::kdfa::>(&seed, &[], &[])?; + let mut hmac = Hmac::::new_from_slice(&hmac_key).map_err(|e| { + error!("HMAC initialization error: {e}"); + Error::local_error(WrapperErrorKind::WrongParamSize) + })?; + Mac::update(&mut hmac, &sensitive_data); + Mac::update(&mut hmac, key_name.value()); + let hmac = hmac.finalize(); + + // We'll now serialize the object and get everything through the door. + let mut out = vec![]; + out.extend_from_slice( + &u16::try_from(hmac.into_bytes().len()) + .map_err(|_| { + // NOTE: this shouldn't ever trigger ... but ... + error!("HMAC output may only be 2^16 bytes long"); + Error::local_error(WrapperErrorKind::WrongParamSize) + })? + .to_be_bytes()[..], + ); + out.extend_from_slice(&hmac.into_bytes()); + out.extend_from_slice(&sensitive_data); + + IdObject::from_bytes(&out).map(Ok) +} diff --git a/tss-esapi/src/utils/kdf.rs b/tss-esapi/src/utils/kdf.rs new file mode 100644 index 00000000..74b2f381 --- /dev/null +++ b/tss-esapi/src/utils/kdf.rs @@ -0,0 +1,243 @@ +// Copyright 2025 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +use core::ops::{Add, Mul}; + +use digest::{ + array::{Array, ArraySize}, + consts::{B1, U3, U6, U7, U8, U9}, + crypto_common::KeySizeUser, + typenum::{ + operator_aliases::{Add1, Sum}, + Unsigned, + }, + Digest, FixedOutputReset, Key, OutputSizeUser, +}; +use ecdsa::elliptic_curve::{ + ecdh::SharedSecret, + point::AffineCoordinates, + sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint}, + AffinePoint, Curve, CurveArithmetic, FieldBytesSize, PublicKey, +}; +use hmac::{EagerHash, Hmac}; +use kbkdf::{Counter, Kbkdf, Params}; +use log::error; + +use crate::{Error, Result, WrapperErrorKind}; + +/// Label to be applied when deriving a key with either [`kdfa`] or [`kdfe`] +// Note: until generic_const_expr stabilize, we will have to carry a const parameter on the trait, +// once that's stable, we should be able to do `const LABEL: [u8; Self::LabelSize]` +// Until then, the preferred implementation would be using `impl_kdf_label` macro, as it should be +// misuse-resistant. +pub trait KdfLabel { + type LabelSize: Unsigned; + const LABEL: &'static [u8]; +} + +macro_rules! impl_kdf_label { + ($usage:ty, $size: ty, $value: expr) => { + impl KdfLabel for $usage { + type LabelSize = $size; + const LABEL: &'static [u8] = { + // This is only to make sure at compile-time the label has the correct size + let _: [u8; <$size>::USIZE] = *$value; + $value + }; + } + }; +} + +#[derive(Copy, Clone, Debug)] +pub struct Secret; +impl_kdf_label!(Secret, U6, b"SECRET"); + +#[derive(Copy, Clone, Debug)] +pub struct Context; +impl_kdf_label!(Context, U7, b"CONTEXT"); + +#[derive(Copy, Clone, Debug)] +pub struct Obfuscate; +impl_kdf_label!(Obfuscate, U9, b"OBFUSCATE"); + +#[derive(Copy, Clone, Debug)] +pub struct Storage; +impl_kdf_label!(Storage, U7, b"STORAGE"); + +#[derive(Copy, Clone, Debug)] +pub struct Integrity; +impl_kdf_label!(Integrity, U9, b"INTEGRITY"); + +#[derive(Copy, Clone, Debug)] +pub struct Commit; +impl_kdf_label!(Commit, U6, b"COMMIT"); + +#[derive(Copy, Clone, Debug)] +pub struct Cfb; +impl_kdf_label!(Cfb, U3, b"CFB"); + +#[derive(Copy, Clone, Debug)] +pub struct Xor; +impl_kdf_label!(Xor, U3, b"XOR"); + +#[derive(Copy, Clone, Debug)] +pub struct Session; +impl_kdf_label!(Session, U7, b"SESSION"); + +#[derive(Copy, Clone, Debug)] +pub struct Identity; +impl_kdf_label!(Identity, U8, b"IDENTITY"); + +type LabelAndUAndV = Add1, FieldBytesSize>, N>>; + +pub fn kdfa(key: &[u8], context_u: &[u8], context_v: &[u8]) -> Result> +where + L: KdfLabel, + + H: Digest + FixedOutputReset + EagerHash, + K: KeySizeUser, + + K::KeySize: ArraySize + Mul, + >::Output: Unsigned, + + <::Core as OutputSizeUser>::OutputSize: ArraySize + Mul, + <<::Core as OutputSizeUser>::OutputSize as Mul>::Output: Unsigned, +{ + let mut context = Vec::with_capacity(context_u.len() + context_v.len()); + context.extend_from_slice(context_u); + context.extend_from_slice(context_v); + + let kdf = Counter::, K>::default(); + kdf.derive( + Params::builder(key) + .with_label(L::LABEL) + .with_context(&context) + .build(), + ) + .map_err(|e| { + error!("KDFa derivation error: {e}"); + Error::local_error(WrapperErrorKind::InternalError) + }) +} + +pub fn kdfe( + z: &SharedSecret, + party_u_info: &PublicKey, + party_v_info: &PublicKey, +) -> Result> +where + L: KdfLabel, + + H: Digest + FixedOutputReset, + C: Curve + CurveArithmetic, + K: KeySizeUser, + + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldBytesSize: ModulusSize, + + as Add>::Output: Add>, + Sum, FieldBytesSize>: Add, + Sum, FieldBytesSize>, L::LabelSize>: Add, + Add1, FieldBytesSize>, L::LabelSize>>: ArraySize, +{ + let mut key = Key::::default(); + + let mut other_info = Array::>::default(); + other_info[..L::LabelSize::USIZE].copy_from_slice(L::LABEL); + other_info[L::LabelSize::USIZE] = 0; + + other_info[L::LabelSize::USIZE + 1..L::LabelSize::USIZE + 1 + FieldBytesSize::::USIZE] + .copy_from_slice(&party_u_info.as_affine().x()); + other_info[L::LabelSize::USIZE + 1 + FieldBytesSize::::USIZE..] + .copy_from_slice(&party_v_info.as_affine().x()); + + concat_kdf::derive_key_into::(z.raw_secret_bytes(), &other_info, &mut key).map_err(|e| { + error!("KDFe derivation error: {e}"); + Error::local_error(WrapperErrorKind::InternalError) + })?; + + Ok(key) +} + +#[cfg(test)] +mod tests { + use super::*; + + use aes::Aes256; + use hex_literal::hex; + use sha2::Sha256; + + #[test] + fn test_kdfe() { + struct Vector { + shared_secret: [u8; S], + local_key: [u8; K], + remote_key: [u8; K], + expected: [u8; E], + } + + // Test vectors here were manually generated from tpm2-pytss + static TEST_VECTORS_SHA256: [Vector< + { FieldBytesSize::::USIZE }, + { as ModulusSize>::CompressedPointSize::USIZE }, + 32, + >; 2] = [ + Vector { + shared_secret: hex!( + "c75afb6f49c941ef194b232d7615769f5152d20de5dee19a991067f337dd65bc" + ), + local_key: hex!( + "031ba4030de068a2f07919c42ef6b19f302884f35f45e7d4e4bb90ffbb0bd9d099" + ), + remote_key: hex!( + "038f2b219a29c2ff9ba69cedff2d08d33a5dbca3da6bc8af8acd3ff6f5ec4dfbef" + ), + expected: hex!("e3a0079db19724f9b76101e9364c4a149cea3501336abc3b603f94b22b6309a5"), + }, + Vector { + shared_secret: hex!( + "a90a1c095155428500ed19e87c0df078df3dd2e66a0e3bbe664ba9ff62113b4a" + ), + local_key: hex!( + "03e9c7d6a853ba6176b65ec2f328bdea25f61c4e1b23a4e1c08e1da8c723381a04" + ), + remote_key: hex!( + "036ccf059628d3cdf8e1b4c4ba6d14696ba51cc8d4a96df4016f0b214782d5cee6" + ), + expected: hex!("865f8093e2c4b801dc8c236eeb2806c7b1c51c2cb04101c035f7f2511ea0aeda"), + }, + ]; + + for v in &TEST_VECTORS_SHA256 { + let out = kdfe::( + &SharedSecret::from(Array::from(v.shared_secret)), + &PublicKey::try_from(Array::from(v.local_key)).unwrap(), + &PublicKey::try_from(Array::from(v.remote_key)).unwrap(), + ) + .unwrap(); + assert_eq!(out, v.expected); + } + } + + #[test] + fn test_kdfa() { + struct Vector { + key: &'static [u8], + context_u: &'static [u8], + context_v: &'static [u8], + expected: &'static [u8], + } + + static TEST_VECTORS_SHA256: [Vector; 1] = [Vector { + key: &hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + context_u: b"", + context_v: &hex!("0506070809"), + expected: &hex!("de275f7f5cfeaac226b30d42377903b34705f178730d96400ccafb736e3d28a4"), + }]; + + for v in &TEST_VECTORS_SHA256 { + let out = kdfa::(&v.key, &v.context_u, &v.context_v).unwrap(); + assert_eq!(out.as_slice(), v.expected); + } + } +} diff --git a/tss-esapi/src/utils/mod.rs b/tss-esapi/src/utils/mod.rs index 3bce9096..556cfb0c 100644 --- a/tss-esapi/src/utils/mod.rs +++ b/tss-esapi/src/utils/mod.rs @@ -23,6 +23,14 @@ use crate::{Context, Error, Result, WrapperErrorKind}; use std::convert::TryFrom; use zeroize::Zeroize; +#[cfg(feature = "rustcrypto")] +mod credential; +#[cfg(feature = "rustcrypto")] +pub mod kdf; + +#[cfg(feature = "rustcrypto")] +pub use self::credential::{make_credential_ecc, make_credential_rsa}; + /// Create the [Public] structure for a restricted decryption key. /// /// * `symmetric` - Cipher to be used for decrypting children of the key diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/credential_tests.rs b/tss-esapi/tests/integration_tests/abstraction_tests/credential_tests.rs new file mode 100644 index 00000000..58b86c2e --- /dev/null +++ b/tss-esapi/tests/integration_tests/abstraction_tests/credential_tests.rs @@ -0,0 +1,222 @@ +// Copyright 2025 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +use tss_esapi::{ + abstraction::{ak, ek, AsymmetricAlgorithmSelection}, + attributes::SessionAttributesBuilder, + constants::SessionType, + handles::AuthHandle, + interface_types::{ + algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, + ecc::EccCurve, + key_bits::RsaKeyBits, + session_handles::PolicySession, + }, + structures::{Digest, SymmetricDefinition}, + utils, +}; + +use elliptic_curve::PublicKey; +use rsa::RsaPublicKey; + +use crate::common::create_ctx_without_session; + +#[test] +fn test_credential_ecc() { + let mut context = create_ctx_without_session(); + + let ek_ecc = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), + None, + ) + .unwrap(); + + let (ek_pub, _, _) = context.read_public(ek_ecc).unwrap(); + + let ak_res = ak::create_ak( + &mut context, + ek_ecc, + HashingAlgorithm::Sha384, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), + SignatureSchemeAlgorithm::EcDsa, + None, + None, + ) + .unwrap(); + + let ak_ecc = ak::load_ak( + &mut context, + ek_ecc, + None, + ak_res.out_private, + ak_res.out_public, + ) + .unwrap(); + + let (_, key_name, _) = context.read_public(ak_ecc).unwrap(); + let cred = vec![1, 2, 3, 4, 5]; + let expected = Digest::try_from(vec![1, 2, 3, 4, 5]).unwrap(); + + let (credential_blob, secret) = utils::make_credential_ecc::<_, sha2::Sha256, aes::Aes128>( + PublicKey::::try_from(&ek_pub).unwrap(), + &cred, + key_name, + ) + .expect("Create credential"); + + let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); + let session_1 = context + .start_auth_session( + None, + None, + None, + SessionType::Hmac, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_1, session_attributes, session_attributes_mask) + .unwrap(); + + let session_2 = context + .start_auth_session( + None, + None, + None, + SessionType::Policy, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_2, session_attributes, session_attributes_mask) + .expect("Failed to call tr_sess_set_attributes"); + + let _ = context + .execute_with_session(Some(session_1), |ctx| { + ctx.policy_secret( + PolicySession::try_from(session_2) + .expect("Failed to convert auth session to policy session"), + AuthHandle::Endorsement, + Default::default(), + Default::default(), + Default::default(), + None, + ) + }) + .unwrap(); + + context.set_sessions((Some(session_1), Some(session_2), None)); + let decrypted = context + .activate_credential(ak_ecc, ek_ecc, credential_blob, secret) + .unwrap(); + + assert_eq!(expected, decrypted); + + context.flush_context(ek_ecc.into()).unwrap(); + context.flush_context(ak_ecc.into()).unwrap(); +} + +#[test] +fn test_credential_rsa() { + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + None, + ) + .unwrap(); + + let (ek_pub, _, _) = context.read_public(ek_rsa).unwrap(); + + let ak_res = ak::create_ak( + &mut context, + ek_rsa, + HashingAlgorithm::Sha256, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + SignatureSchemeAlgorithm::RsaPss, + None, + None, + ) + .unwrap(); + + let ak_rsa = ak::load_ak( + &mut context, + ek_rsa, + None, + ak_res.out_private, + ak_res.out_public, + ) + .unwrap(); + + let (_, key_name, _) = context.read_public(ak_rsa).unwrap(); + let cred = vec![1, 2, 3, 4, 5]; + let expected = Digest::try_from(vec![1, 2, 3, 4, 5]).unwrap(); + + let (credential_blob, secret) = utils::make_credential_rsa::( + &RsaPublicKey::try_from(&ek_pub).unwrap(), + &cred, + key_name, + ) + .expect("Create credential"); + + let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); + let session_1 = context + .start_auth_session( + None, + None, + None, + SessionType::Hmac, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_1, session_attributes, session_attributes_mask) + .unwrap(); + + let session_2 = context + .start_auth_session( + None, + None, + None, + SessionType::Policy, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_2, session_attributes, session_attributes_mask) + .expect("Failed to call tr_sess_set_attributes"); + + let _ = context + .execute_with_session(Some(session_1), |ctx| { + ctx.policy_secret( + PolicySession::try_from(session_2) + .expect("Failed to convert auth session to policy session"), + AuthHandle::Endorsement, + Default::default(), + Default::default(), + Default::default(), + None, + ) + }) + .unwrap(); + + context.set_sessions((Some(session_1), Some(session_2), None)); + let decrypted = context + .activate_credential(ak_rsa, ek_rsa, credential_blob, secret) + .unwrap(); + + assert_eq!(expected, decrypted); + + context.flush_context(ek_rsa.into()).unwrap(); + context.flush_context(ak_rsa.into()).unwrap(); +} diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs b/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs index 2d56d05e..0e2b500a 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs @@ -1,6 +1,7 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod ak_tests; +mod credential_tests; mod ek_tests; mod no_tpm; mod nv_tests; diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs b/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs index cd41a8c6..e608e6d1 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs @@ -902,10 +902,10 @@ fn sign_csr() { let subject = Name::from_str("CN=tpm.example").expect("Parse common name"); let signer = EcSigner::::new((Mutex::new(&mut ctx), tpm_km, key_params, None)) .expect("Create a signer"); - let builder = RequestBuilder::new(subject, &signer).expect("Create certificate request"); + let builder = RequestBuilder::new(subject).expect("Create certificate request"); let cert_req = builder - .build::() + .build::<_, p256::ecdsa::DerSignature>(&signer) .expect("Sign a CSR"); println!(