Skip to content

Commit 6525f15

Browse files
committed
adds a signature::Signer implementation for ecc keys
Signed-off-by: Arthur Gautier <[email protected]>
1 parent 05b7c15 commit 6525f15

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed

tss-esapi/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ zeroize = { version = "1.5.7", features = ["zeroize_derive"] }
2929
tss-esapi-sys = { path = "../tss-esapi-sys", version = "0.5.0" }
3030
x509-cert = { version = "0.2.0", optional = true }
3131
elliptic-curve = { version = "0.13.8", optional = true, features = ["alloc", "pkcs8"] }
32+
ecdsa = { version = "0.16.9" }
3233
p192 = { version = "0.13.0", optional = true }
3334
p224 = { version = "0.13.2", optional = true }
3435
p256 = { version = "0.13.2", optional = true }
@@ -41,6 +42,7 @@ sha3 = { version = "0.10.8", optional = true }
4142
sm2 = { version = "0.13.3", optional = true }
4243
sm3 = { version = "0.4.2", optional = true }
4344
digest = "0.10.7"
45+
signature = "2.2.0"
4446
cfg-if = "1.0.0"
4547
strum = { version = "0.25.0", optional = true }
4648
strum_macros = { version = "0.25.0", optional = true }

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

+2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ use std::convert::{AsMut, AsRef, TryFrom, TryInto};
3434
use zeroize::Zeroize;
3535

3636
mod key_attestation;
37+
mod signer;
3738

3839
pub use key_attestation::MakeCredParams;
40+
pub use signer::Ecdsa;
3941

4042
/// Parameters for the kinds of keys supported by the context
4143
#[derive(Debug, Clone, Copy)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright 2019 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Module for exposing a [`signature::Signer`] interface for keys
5+
//!
6+
//! This modules presents objects held in a TPM over a [`signature::DigestSigner`] interface.
7+
use super::TransientKeyContext;
8+
use crate::{
9+
abstraction::{
10+
public::AssociatedTpmCurve,
11+
transient::{KeyMaterial, KeyParams},
12+
},
13+
interface_types::algorithm::{AssociatedHashingAlgorithm, EccSchemeAlgorithm},
14+
structures::{Auth, Digest as TpmDigest, EccScheme, Signature as TpmSignature},
15+
Error,
16+
};
17+
18+
use std::{convert::TryFrom, ops::Add, sync::Mutex};
19+
20+
use digest::{Digest, FixedOutput, Output};
21+
use ecdsa::{
22+
der::{MaxOverhead, MaxSize, Signature as DerSignature},
23+
hazmat::{DigestPrimitive, SignPrimitive},
24+
Signature, SignatureSize, VerifyingKey,
25+
};
26+
use elliptic_curve::{
27+
generic_array::ArrayLength,
28+
ops::Invert,
29+
sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint},
30+
subtle::CtOption,
31+
AffinePoint, CurveArithmetic, FieldBytesSize, PrimeCurve, PublicKey, Scalar,
32+
};
33+
use signature::{DigestSigner, Error as SError, KeypairRef};
34+
35+
#[derive(Debug)]
36+
pub struct Ecdsa<'ctx, C>
37+
where
38+
C: PrimeCurve + CurveArithmetic,
39+
{
40+
context: Mutex<&'ctx mut TransientKeyContext>,
41+
key_material: KeyMaterial,
42+
key_auth: Option<Auth>,
43+
verifying_key: VerifyingKey<C>,
44+
}
45+
46+
impl<'ctx, C> Ecdsa<'ctx, C>
47+
where
48+
C: PrimeCurve + CurveArithmetic,
49+
C: AssociatedTpmCurve,
50+
FieldBytesSize<C>: ModulusSize,
51+
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
52+
{
53+
pub fn new(
54+
context: &'ctx mut TransientKeyContext,
55+
key_material: KeyMaterial,
56+
key_auth: Option<Auth>,
57+
) -> Result<Self, Error> {
58+
let context = Mutex::new(context);
59+
60+
let public_key = PublicKey::try_from(key_material.public())?;
61+
let verifying_key = VerifyingKey::from(public_key);
62+
63+
Ok(Self {
64+
context,
65+
key_material,
66+
key_auth,
67+
verifying_key,
68+
})
69+
}
70+
}
71+
72+
impl<'ctx, C> Ecdsa<'ctx, C>
73+
where
74+
C: PrimeCurve + CurveArithmetic,
75+
C: AssociatedTpmCurve,
76+
{
77+
/// Key parameters for this curve
78+
pub fn key_params_default() -> KeyParams
79+
where
80+
C: DigestPrimitive,
81+
<C as DigestPrimitive>::Digest: AssociatedHashingAlgorithm,
82+
{
83+
Self::key_params::<C::Digest>()
84+
}
85+
86+
/// Key parameters for this curve
87+
pub fn key_params<D>() -> KeyParams
88+
where
89+
D: AssociatedHashingAlgorithm,
90+
{
91+
KeyParams::Ecc {
92+
curve: C::TPM_CURVE,
93+
scheme: EccScheme::create(EccSchemeAlgorithm::EcDsa, Some(D::TPM_DIGEST), None)
94+
.expect("Failed to create ecc scheme"),
95+
}
96+
}
97+
}
98+
99+
impl<'ctx, C> AsRef<VerifyingKey<C>> for Ecdsa<'ctx, C>
100+
where
101+
C: PrimeCurve + CurveArithmetic,
102+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
103+
SignatureSize<C>: ArrayLength<u8>,
104+
{
105+
fn as_ref(&self) -> &VerifyingKey<C> {
106+
&self.verifying_key
107+
}
108+
}
109+
110+
impl<'ctx, C> KeypairRef for Ecdsa<'ctx, C>
111+
where
112+
C: PrimeCurve + CurveArithmetic,
113+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
114+
SignatureSize<C>: ArrayLength<u8>,
115+
{
116+
type VerifyingKey = VerifyingKey<C>;
117+
}
118+
119+
impl<'ctx, C, D> DigestSigner<D, Signature<C>> for Ecdsa<'ctx, C>
120+
where
121+
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
122+
C: AssociatedTpmCurve,
123+
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
124+
D: AssociatedHashingAlgorithm,
125+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
126+
SignatureSize<C>: ArrayLength<u8>,
127+
TpmDigest: From<Output<D>>,
128+
{
129+
fn try_sign_digest(&self, digest: D) -> Result<Signature<C>, SError> {
130+
let digest = TpmDigest::from(digest.finalize_fixed());
131+
132+
let key_params = Self::key_params::<D>();
133+
let mut context = self.context.lock().unwrap();
134+
let signature = context
135+
.sign(
136+
self.key_material.clone(),
137+
key_params,
138+
self.key_auth.clone(),
139+
digest,
140+
)
141+
.unwrap();
142+
let TpmSignature::EcDsa(signature) = signature else {
143+
todo!();
144+
};
145+
146+
let signature = Signature::try_from(signature).unwrap();
147+
148+
Ok(signature)
149+
}
150+
}
151+
152+
impl<'ctx, C, D> DigestSigner<D, DerSignature<C>> for Ecdsa<'ctx, C>
153+
where
154+
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
155+
C: AssociatedTpmCurve,
156+
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
157+
D: AssociatedHashingAlgorithm,
158+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
159+
SignatureSize<C>: ArrayLength<u8>,
160+
TpmDigest: From<Output<D>>,
161+
162+
MaxSize<C>: ArrayLength<u8>,
163+
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
164+
{
165+
fn try_sign_digest(&self, digest: D) -> Result<DerSignature<C>, SError> {
166+
let signature: Signature<_> = self.try_sign_digest(digest)?;
167+
Ok(signature.to_der())
168+
}
169+
}

0 commit comments

Comments
 (0)