Skip to content

Commit ca00fb5

Browse files
committed
Signer should support non-transient keys
Signed-off-by: Arthur Gautier <[email protected]>
1 parent 6f487cc commit ca00fb5

File tree

5 files changed

+175
-63
lines changed

5 files changed

+175
-63
lines changed

tss-esapi/src/abstraction/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ pub mod transient;
1111

1212
mod hashing;
1313
mod signatures;
14+
mod signer;
1415
pub use hashing::AssociatedHashingAlgorithm;
16+
pub use signer::EcSigner;
1517

1618
use std::convert::TryFrom;
1719

tss-esapi/src/abstraction/transient/signer.rs renamed to tss-esapi/src/abstraction/signer.rs

Lines changed: 112 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
//! Module for exposing a [`signature::Signer`] interface for keys
55
//!
66
//! This modules presents objects held in a TPM over a [`signature::DigestSigner`] interface.
7-
use super::TransientKeyContext;
87
use crate::{
98
abstraction::{
109
public::AssociatedTpmCurve,
11-
transient::{KeyMaterial, KeyParams},
10+
transient::{KeyMaterial, KeyParams, TransientKeyContext},
1211
AssociatedHashingAlgorithm,
1312
},
13+
handles::KeyHandle,
1414
interface_types::algorithm::EccSchemeAlgorithm,
15-
structures::{Auth, Digest as TpmDigest, EccScheme, Signature as TpmSignature},
16-
Error, WrapperErrorKind,
15+
structures::{
16+
Auth, Digest as TpmDigest, EccScheme, Public, Signature as TpmSignature, SignatureScheme,
17+
},
18+
utils::PublicKey as TpmPublicKey,
19+
Context, Error, WrapperErrorKind,
1720
};
1821

1922
use std::{convert::TryFrom, ops::Add, sync::Mutex};
@@ -31,21 +34,86 @@ use elliptic_curve::{
3134
subtle::CtOption,
3235
AffinePoint, CurveArithmetic, FieldBytesSize, PrimeCurve, PublicKey, Scalar,
3336
};
37+
use log::error;
3438
use signature::{DigestSigner, Error as SigError, KeypairRef, Signer};
3539
use x509_cert::{
3640
der::asn1::AnyRef,
3741
spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier},
3842
};
3943

44+
pub trait TpmSigner {
45+
fn public(&self) -> crate::Result<TpmPublicKey>;
46+
fn key_params(&self) -> crate::Result<KeyParams>;
47+
fn sign(&self, digest: TpmDigest) -> crate::Result<TpmSignature>;
48+
}
49+
50+
impl TpmSigner for (Mutex<&'_ mut Context>, KeyHandle) {
51+
fn public(&self) -> crate::Result<TpmPublicKey> {
52+
let mut context = self.0.lock().expect("Mutex got poisoned");
53+
let (public, _, _) = context.read_public(self.1)?;
54+
55+
TpmPublicKey::try_from(public)
56+
}
57+
58+
fn key_params(&self) -> crate::Result<KeyParams> {
59+
let mut context = self.0.lock().expect("Mutex got poisoned");
60+
let (public, _, _) = context.read_public(self.1)?;
61+
62+
match public {
63+
Public::Rsa { parameters, .. } => Ok(KeyParams::Rsa {
64+
size: parameters.key_bits(),
65+
scheme: parameters.rsa_scheme(),
66+
pub_exponent: parameters.exponent(),
67+
}),
68+
Public::Ecc { parameters, .. } => Ok(KeyParams::Ecc {
69+
curve: parameters.ecc_curve(),
70+
scheme: parameters.ecc_scheme(),
71+
}),
72+
other => {
73+
error!("Unsupported key parameter used: {other:?}");
74+
Err(Error::local_error(WrapperErrorKind::InvalidParam))
75+
}
76+
}
77+
}
78+
79+
fn sign(&self, digest: TpmDigest) -> crate::Result<TpmSignature> {
80+
let mut context = self.0.lock().expect("Mutex got poisoned");
81+
context.sign(self.1, digest, SignatureScheme::Null, None)
82+
}
83+
}
84+
85+
impl TpmSigner
86+
for (
87+
Mutex<&'_ mut TransientKeyContext>,
88+
KeyMaterial,
89+
KeyParams,
90+
Option<Auth>,
91+
)
92+
{
93+
fn public(&self) -> crate::Result<TpmPublicKey> {
94+
Ok(self.1.public().clone())
95+
}
96+
97+
fn key_params(&self) -> crate::Result<KeyParams> {
98+
Ok(self.2)
99+
}
100+
101+
fn sign(&self, digest: TpmDigest) -> crate::Result<TpmSignature> {
102+
let mut context = self.0.lock().expect("Mutex got poisoned");
103+
context.sign(self.1.clone(), self.2, self.3.clone(), digest)
104+
}
105+
}
106+
40107
/// [`EcSigner`] will sign a payload with an elliptic curve secret key stored on the TPM.
41108
///
42109
/// # Parameters
43110
///
44111
/// Parameter `C` describes the curve that is of use (Nist P-256, Nist P-384, ...)
45112
///
46113
/// ```no_run
114+
/// # use std::sync::Mutex;
47115
/// # use tss_esapi::{
48-
/// # abstraction::transient::{EcSigner, TransientKeyContextBuilder},
116+
/// # abstraction::{EcSigner, transient::TransientKeyContextBuilder},
49117
/// # TctiNameConf
50118
/// # };
51119
/// use p256::NistP256;
@@ -59,52 +127,57 @@ use x509_cert::{
59127
/// # .build()
60128
/// # .expect("Failed to create Context");
61129
///
130+
/// let key_params = EcSigner::<NistP256, ()>::key_params_default();
62131
/// let (tpm_km, _tpm_auth) = context
63-
/// .create_key(EcSigner::<NistP256>::key_params_default(), 0)
132+
/// .create_key(key_params, 0)
64133
/// .expect("Failed to create a private keypair");
65134
///
66-
/// let signer = EcSigner::<NistP256>::new(&mut context, tpm_km, None)
135+
/// let signer = EcSigner::<NistP256,_>::new((Mutex::new(&mut context), tpm_km, key_params, None))
67136
/// .expect("Failed to create a signer");
68137
/// let signature: p256::ecdsa::Signature = signer.sign(b"Hello Bob, Alice here.");
69138
/// ```
70139
#[derive(Debug)]
71-
pub struct EcSigner<'ctx, C>
140+
pub struct EcSigner<C, Ctx>
72141
where
73142
C: PrimeCurve + CurveArithmetic,
74143
{
75-
context: Mutex<&'ctx mut TransientKeyContext>,
76-
key_material: KeyMaterial,
77-
key_auth: Option<Auth>,
144+
context: Ctx,
78145
verifying_key: VerifyingKey<C>,
79146
}
80147

81-
impl<'ctx, C> EcSigner<'ctx, C>
148+
impl<C, Ctx> EcSigner<C, Ctx>
82149
where
83150
C: PrimeCurve + CurveArithmetic,
84151
C: AssociatedTpmCurve,
85152
FieldBytesSize<C>: ModulusSize,
86153
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
154+
155+
Ctx: TpmSigner,
87156
{
88-
pub fn new(
89-
context: &'ctx mut TransientKeyContext,
90-
key_material: KeyMaterial,
91-
key_auth: Option<Auth>,
92-
) -> Result<Self, Error> {
93-
let context = Mutex::new(context);
94-
95-
let public_key = PublicKey::try_from(key_material.public())?;
157+
pub fn new(context: Ctx) -> Result<Self, Error> {
158+
match context.key_params()? {
159+
KeyParams::Ecc { curve, .. } if curve == C::TPM_CURVE => {}
160+
other => {
161+
error!(
162+
"Unsupported key parameters: {other:?}, expected Ecc(curve: {:?})",
163+
C::default()
164+
);
165+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
166+
}
167+
}
168+
169+
let public_key = context.public()?;
170+
let public_key = PublicKey::try_from(&public_key)?;
96171
let verifying_key = VerifyingKey::from(public_key);
97172

98173
Ok(Self {
99174
context,
100-
key_material,
101-
key_auth,
102175
verifying_key,
103176
})
104177
}
105178
}
106179

107-
impl<C> EcSigner<'_, C>
180+
impl<C, Ctx> EcSigner<C, Ctx>
108181
where
109182
C: PrimeCurve + CurveArithmetic,
110183
C: AssociatedTpmCurve,
@@ -137,7 +210,7 @@ where
137210
}
138211
}
139212

140-
impl<C> AsRef<VerifyingKey<C>> for EcSigner<'_, C>
213+
impl<C, Ctx> AsRef<VerifyingKey<C>> for EcSigner<C, Ctx>
141214
where
142215
C: PrimeCurve + CurveArithmetic,
143216
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
@@ -148,7 +221,7 @@ where
148221
}
149222
}
150223

151-
impl<C> KeypairRef for EcSigner<'_, C>
224+
impl<C, Ctx> KeypairRef for EcSigner<C, Ctx>
152225
where
153226
C: PrimeCurve + CurveArithmetic,
154227
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
@@ -157,7 +230,7 @@ where
157230
type VerifyingKey = VerifyingKey<C>;
158231
}
159232

160-
impl<C, D> DigestSigner<D, Signature<C>> for EcSigner<'_, C>
233+
impl<C, Ctx, D> DigestSigner<D, Signature<C>> for EcSigner<C, Ctx>
161234
where
162235
C: PrimeCurve + CurveArithmetic,
163236
C: AssociatedTpmCurve,
@@ -166,20 +239,13 @@ where
166239
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
167240
SignatureSize<C>: ArrayLength<u8>,
168241
TpmDigest: From<Output<D>>,
242+
Ctx: TpmSigner,
169243
{
170244
fn try_sign_digest(&self, digest: D) -> Result<Signature<C>, SigError> {
171245
let digest = TpmDigest::from(digest.finalize_fixed());
172246

173-
let key_params = Self::key_params::<D>();
174-
let mut context = self.context.lock().expect("Mutex got poisoned");
175-
let signature = context
176-
.sign(
177-
self.key_material.clone(),
178-
key_params,
179-
self.key_auth.clone(),
180-
digest,
181-
)
182-
.map_err(SigError::from_source)?;
247+
//let key_params = Self::key_params::<D>();
248+
let signature = self.context.sign(digest).map_err(SigError::from_source)?;
183249

184250
let TpmSignature::EcDsa(signature) = signature else {
185251
return Err(SigError::from_source(Error::local_error(
@@ -193,7 +259,7 @@ where
193259
}
194260
}
195261

196-
impl<C, D> DigestSigner<D, DerSignature<C>> for EcSigner<'_, C>
262+
impl<C, Ctx, D> DigestSigner<D, DerSignature<C>> for EcSigner<C, Ctx>
197263
where
198264
C: PrimeCurve + CurveArithmetic,
199265
C: AssociatedTpmCurve,
@@ -205,28 +271,32 @@ where
205271

206272
MaxSize<C>: ArrayLength<u8>,
207273
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
274+
275+
Ctx: TpmSigner,
208276
{
209277
fn try_sign_digest(&self, digest: D) -> Result<DerSignature<C>, SigError> {
210278
let signature: Signature<_> = self.try_sign_digest(digest)?;
211279
Ok(signature.to_der())
212280
}
213281
}
214282

215-
impl<C> Signer<Signature<C>> for EcSigner<'_, C>
283+
impl<C, Ctx> Signer<Signature<C>> for EcSigner<C, Ctx>
216284
where
217285
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
218286
C: AssociatedTpmCurve,
219287
<C as DigestPrimitive>::Digest: AssociatedHashingAlgorithm,
220288
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
221289
SignatureSize<C>: ArrayLength<u8>,
222290
TpmDigest: From<Output<<C as DigestPrimitive>::Digest>>,
291+
292+
Ctx: TpmSigner,
223293
{
224294
fn try_sign(&self, msg: &[u8]) -> Result<Signature<C>, SigError> {
225295
self.try_sign_digest(C::Digest::new_with_prefix(msg))
226296
}
227297
}
228298

229-
impl<C> Signer<DerSignature<C>> for EcSigner<'_, C>
299+
impl<C, Ctx> Signer<DerSignature<C>> for EcSigner<C, Ctx>
230300
where
231301
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
232302
C: AssociatedTpmCurve,
@@ -237,13 +307,15 @@ where
237307

238308
MaxSize<C>: ArrayLength<u8>,
239309
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
310+
311+
Ctx: TpmSigner,
240312
{
241313
fn try_sign(&self, msg: &[u8]) -> Result<DerSignature<C>, SigError> {
242314
self.try_sign_digest(C::Digest::new_with_prefix(msg))
243315
}
244316
}
245317

246-
impl<C> SignatureAlgorithmIdentifier for EcSigner<'_, C>
318+
impl<C, Ctx> SignatureAlgorithmIdentifier for EcSigner<C, Ctx>
247319
where
248320
C: PrimeCurve + CurveArithmetic,
249321
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,

tss-esapi/src/abstraction/transient/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,8 @@ use zeroize::Zeroize;
3535

3636
mod key_attestation;
3737

38-
mod signer;
39-
4038
pub use key_attestation::MakeCredParams;
4139

42-
pub use signer::EcSigner;
43-
4440
/// Parameters for the kinds of keys supported by the context
4541
#[derive(Debug, Clone, Copy)]
4642
pub enum KeyParams {

tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
use std::{
44
convert::{TryFrom, TryInto},
55
str::FromStr,
6+
sync::Mutex,
67
};
78
use tss_esapi::{
8-
abstraction::transient::{EcSigner, KeyParams, ObjectWrapper, TransientKeyContextBuilder},
9-
abstraction::{ek, AsymmetricAlgorithmSelection},
9+
abstraction::transient::{KeyParams, ObjectWrapper, TransientKeyContextBuilder},
10+
abstraction::{ek, AsymmetricAlgorithmSelection, EcSigner},
1011
constants::return_code::{TpmFormatOneError, TpmFormatZeroError},
1112
error::{TpmFormatZeroResponseCode, TpmResponseCode},
1213
interface_types::{
@@ -895,12 +896,12 @@ fn sign_csr() {
895896
// Check that we can convert a reference from TKC to Context
896897
let mut ctx = create_ctx();
897898

898-
let (tpm_km, _tpm_auth) = ctx
899-
.create_key(EcSigner::<NistP256>::key_params_default(), 0)
900-
.expect("create private key");
899+
let key_params = EcSigner::<NistP256, ()>::key_params_default();
900+
let (tpm_km, _tpm_auth) = ctx.create_key(key_params, 0).expect("create private key");
901901

902902
let subject = Name::from_str("CN=tpm.example").expect("Parse common name");
903-
let signer = EcSigner::<NistP256>::new(&mut ctx, tpm_km, None).expect("Create a signer");
903+
let signer = EcSigner::<NistP256, _>::new((Mutex::new(&mut ctx), tpm_km, key_params, None))
904+
.expect("Create a signer");
904905
let builder = RequestBuilder::new(subject, &signer).expect("Create certificate request");
905906

906907
let cert_req = builder
@@ -920,10 +921,10 @@ fn sign_p256_sha2_256() {
920921
// Check that we can convert a reference from TKC to Context
921922
let mut ctx = create_ctx();
922923

923-
let (tpm_km, _tpm_auth) = ctx
924-
.create_key(EcSigner::<NistP256>::key_params::<sha2::Sha256>(), 0)
925-
.expect("create private key");
926-
let signer = EcSigner::<NistP256>::new(&mut ctx, tpm_km, None).expect("Create a signer");
924+
let key_params = EcSigner::<NistP256, ()>::key_params::<sha2::Sha256>();
925+
let (tpm_km, _tpm_auth) = ctx.create_key(key_params, 0).expect("create private key");
926+
let signer = EcSigner::<NistP256, _>::new((Mutex::new(&mut ctx), tpm_km, key_params, None))
927+
.expect("Create a signer");
927928

928929
let payload = b"Example of ECDSA with P-256";
929930
let mut hash = Sha256::new();
@@ -951,20 +952,19 @@ fn sign_p256_sha3_256() {
951952
// Check that we can convert a reference from TKC to Context
952953
let mut ctx = create_ctx();
953954

954-
let (tpm_km, _tpm_auth) = ctx
955-
.create_key(EcSigner::<NistP256>::key_params::<Sha3_256>(), 0)
956-
.expect("create private key");
957-
let signer = EcSigner::<NistP256>::new(&mut ctx, tpm_km, None).expect("Create a signer");
955+
let key_params = EcSigner::<NistP256, ()>::key_params::<Sha3_256>();
956+
let (tpm_km, _tpm_auth) = ctx.create_key(key_params, 0).expect("create private key");
957+
let signer = EcSigner::<NistP256, _>::new((Mutex::new(&mut ctx), tpm_km, key_params, None))
958+
.expect("Create a signer");
958959

959960
let payload = b"Example of ECDSA with P-256";
960961
let mut hash = Sha3_256::new();
961962
hash.update(payload);
962963

963-
let signature =
964-
<EcSigner<'_, _> as DigestSigner<Sha3_256, p256::ecdsa::Signature>>::sign_digest(
965-
&signer,
966-
hash.clone(),
967-
);
964+
let signature = <EcSigner<_, _> as DigestSigner<Sha3_256, p256::ecdsa::Signature>>::sign_digest(
965+
&signer,
966+
hash.clone(),
967+
);
968968
let verifying_key: VerifyingKey = *signer.as_ref();
969969
assert!(verifying_key.verify_digest(hash, &signature).is_ok());
970970
}

0 commit comments

Comments
 (0)