Skip to content

Commit

Permalink
adds a signature::Signer implementation for ecc keys
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Gautier <[email protected]>
  • Loading branch information
baloo committed Aug 3, 2024
1 parent cbba812 commit 85783cc
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tss-esapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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 }
elliptic-curve = { version = "0.13.8", optional = true, features = ["alloc", "pkcs8"] }
ecdsa = { version = "0.16.9" }
p192 = { version = "0.13.0", optional = true }
p224 = { version = "0.13.2", optional = true }
p256 = { version = "0.13.2", optional = true }
Expand All @@ -41,6 +42,7 @@ sha3 = { version = "0.10.8", optional = true }
sm2 = { version = "0.13.3", optional = true }
sm3 = { version = "0.4.2", optional = true }
digest = "0.10.7"
signature = "2.2.0"
cfg-if = "1.0.0"
strum = { version = "0.25.0", optional = true }
strum_macros = { version = "0.25.0", optional = true }
Expand Down
2 changes: 2 additions & 0 deletions tss-esapi/src/abstraction/transient/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ use std::convert::{AsMut, AsRef, TryFrom, TryInto};
use zeroize::Zeroize;

mod key_attestation;
mod signer;

pub use key_attestation::MakeCredParams;
pub use signer::Ecdsa;

/// Parameters for the kinds of keys supported by the context
#[derive(Debug, Clone, Copy)]
Expand Down
169 changes: 169 additions & 0 deletions tss-esapi/src/abstraction/transient/signer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright 2019 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0

//! Module for exposing a [`signature::Signer`] interface for keys
//!
//! This modules presents objects held in a TPM over a [`signature::DigestSigner`] interface.
use super::TransientKeyContext;
use crate::{
abstraction::{
public::AssociatedTpmCurve,
transient::{KeyMaterial, KeyParams},
},
interface_types::algorithm::{AssociatedHashingAlgorithm, EccSchemeAlgorithm},
structures::{Auth, Digest as TpmDigest, EccScheme, Signature as TpmSignature},
Error,
};

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,
};
use elliptic_curve::{
generic_array::ArrayLength,
ops::Invert,
sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint},
subtle::CtOption,
AffinePoint, CurveArithmetic, FieldBytesSize, PrimeCurve, PublicKey, Scalar,
};
use signature::{DigestSigner, Error as SError, KeypairRef};

#[derive(Debug)]
pub struct Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic,
{
context: Mutex<&'ctx mut TransientKeyContext>,
key_material: KeyMaterial,
key_auth: Option<Auth>,
verifying_key: VerifyingKey<C>,
}

impl<'ctx, C> Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic,
C: AssociatedTpmCurve,
FieldBytesSize<C>: ModulusSize,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
{
pub fn new(
context: &'ctx mut TransientKeyContext,
key_material: KeyMaterial,
key_auth: Option<Auth>,
) -> Result<Self, Error> {
let context = Mutex::new(context);

let public_key = PublicKey::try_from(key_material.public())?;
let verifying_key = VerifyingKey::from(public_key);

Ok(Self {
context,
key_material,
key_auth,
verifying_key,
})
}
}

impl<'ctx, C> Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic,
C: AssociatedTpmCurve,
{
/// Key parameters for this curve
pub fn key_params_default() -> KeyParams
where
C: DigestPrimitive,
<C as DigestPrimitive>::Digest: AssociatedHashingAlgorithm,
{
Self::key_params::<C::Digest>()
}

/// Key parameters for this curve
pub fn key_params<D>() -> KeyParams
where
D: AssociatedHashingAlgorithm,
{
KeyParams::Ecc {
curve: C::TPM_CURVE,
scheme: EccScheme::create(EccSchemeAlgorithm::EcDsa, Some(D::TPM_DIGEST), None)
.expect("Failed to create ecc scheme"),
}
}
}

impl<'ctx, C> AsRef<VerifyingKey<C>> for Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
fn as_ref(&self) -> &VerifyingKey<C> {
&self.verifying_key
}
}

impl<'ctx, C> KeypairRef for Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
{
type VerifyingKey = VerifyingKey<C>;
}

impl<'ctx, C, D> DigestSigner<D, Signature<C>> for Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
C: AssociatedTpmCurve,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
D: AssociatedHashingAlgorithm,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
TpmDigest: From<Output<D>>,
{
fn try_sign_digest(&self, digest: D) -> Result<Signature<C>, SError> {
let digest = TpmDigest::from(digest.finalize_fixed());

let key_params = Self::key_params::<D>();
let mut context = self.context.lock().unwrap();
let signature = context
.sign(
self.key_material.clone(),
key_params,
self.key_auth.clone(),
digest,
)
.unwrap();
let TpmSignature::EcDsa(signature) = signature else {
todo!();
};

let signature = Signature::try_from(signature).unwrap();

Ok(signature)
}
}

impl<'ctx, C, D> DigestSigner<D, DerSignature<C>> for Ecdsa<'ctx, C>
where
C: PrimeCurve + CurveArithmetic + DigestPrimitive,
C: AssociatedTpmCurve,
D: Digest + FixedOutput<OutputSize = FieldBytesSize<C>>,
D: AssociatedHashingAlgorithm,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
TpmDigest: From<Output<D>>,

MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
{
fn try_sign_digest(&self, digest: D) -> Result<DerSignature<C>, SError> {
let signature: Signature<_> = self.try_sign_digest(digest)?;
Ok(signature.to_der())
}
}

0 comments on commit 85783cc

Please sign in to comment.