Skip to content

Commit

Permalink
ecdsa: implement key import
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Gautier <[email protected]>
  • Loading branch information
baloo committed Feb 24, 2024
1 parent 5254651 commit b1de50d
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 10 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cryptoki-rustcrypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ x509-cert = "0.2.4"
thiserror = "1.0"

[dev-dependencies]
rand = "0.8.5"
serial_test = "0.5.1"
testresult = "0.2.0"
x509-cert = { version = "0.2.4", features = ["builder"] }
65 changes: 58 additions & 7 deletions cryptoki-rustcrypto/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ use cryptoki::{
object::{Attribute, AttributeType, KeyType, ObjectClass, ObjectHandle},
};
use der::{
asn1::{ObjectIdentifier, OctetStringRef},
asn1::{ObjectIdentifier, OctetString, OctetStringRef},
oid::AssociatedOid,
AnyRef, Decode, Encode,
};
use ecdsa::{
elliptic_curve::{
generic_array::ArrayLength,
ops::Invert,
point::PointCompression,
sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint},
AffinePoint, CurveArithmetic, FieldBytesSize, PublicKey,
subtle::CtOption,
AffinePoint, CurveArithmetic, FieldBytesSize, PublicKey, Scalar,
},
hazmat::DigestPrimitive,
PrimeCurve, Signature, VerifyingKey,
hazmat::{DigestPrimitive, SignPrimitive},
PrimeCurve, Signature, SignatureSize, SigningKey, VerifyingKey,
};
use signature::{digest::Digest, DigestSigner};
use spki::{
Expand All @@ -27,7 +30,7 @@ use spki::{
use std::{convert::TryFrom, ops::Add};
use thiserror::Error;

use crate::SessionLike;
use crate::{CryptokiImport, SessionLike};

pub fn read_key<S: SessionLike, C: SignAlgorithm>(
session: &S,
Expand Down Expand Up @@ -70,6 +73,56 @@ where
}
}

impl<C> CryptokiImport for SigningKey<C>
where
C: PrimeCurve + CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,

C: AssociatedOid,
{
fn put_key<S: SessionLike>(
&self,
session: &S,
template: impl Into<Vec<Attribute>>,
) -> cryptoki::error::Result<ObjectHandle> {
let mut template = template.into();
template.push(Attribute::Class(ObjectClass::PRIVATE_KEY));
template.push(Attribute::KeyType(KeyType::EC));
template.push(Attribute::EcParams(C::OID.to_der().unwrap()));
template.push(Attribute::Value(self.to_bytes().as_slice().to_vec()));

let handle = session.create_object(&template)?;

Ok(handle)
}
}

impl<C> CryptokiImport for VerifyingKey<C>
where
C: PrimeCurve + CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldBytesSize<C>: ModulusSize,
C: AssociatedOid,
{
fn put_key<S: SessionLike>(
&self,
session: &S,
template: impl Into<Vec<Attribute>>,
) -> cryptoki::error::Result<ObjectHandle> {
let mut template = template.into();
template.push(Attribute::Class(ObjectClass::PUBLIC_KEY));
template.push(Attribute::KeyType(KeyType::EC));
template.push(Attribute::EcParams(C::OID.to_der().unwrap()));
let ec_point = OctetString::new(self.to_sec1_bytes()).unwrap();
template.push(Attribute::EcPoint(ec_point.to_der().unwrap()));

let handle = session.create_object(&template)?;

Ok(handle)
}
}

#[derive(Error, Debug)]
pub enum Error {
#[error("Cryptoki error: {0}")]
Expand Down Expand Up @@ -119,8 +172,6 @@ where
pub fn new(session: S, label: &[u8]) -> Result<Self, Error> {
// First we'll lookup a private key with that label.
let template = vec![
Attribute::Token(true),
Attribute::Private(true),
Attribute::Label(label.to_vec()),
Attribute::Class(ObjectClass::PRIVATE_KEY),
Attribute::KeyType(KeyType::EC),
Expand Down
8 changes: 8 additions & 0 deletions cryptoki-rustcrypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ impl<'s> SessionLike for &'s Session {
Session::generate_random_slice(self, random_data)
}
}

pub trait CryptokiImport {
fn put_key<S: SessionLike>(
&self,
session: &S,
template: impl Into<Vec<Attribute>>,
) -> Result<ObjectHandle>;
}
45 changes: 42 additions & 3 deletions cryptoki-rustcrypto/tests/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use cryptoki::{
session::UserType,
types::AuthPin,
};
use cryptoki_rustcrypto::ecdsa;
use cryptoki_rustcrypto::{ecdsa, CryptokiImport};
use der::Encode;
use p256::pkcs8::AssociatedOid;
use serial_test::serial;
Expand Down Expand Up @@ -39,7 +39,7 @@ fn sign_verify() -> TestResult {

// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Token(false),
Attribute::Private(false),
Attribute::KeyType(KeyType::EC),
Attribute::Verify(true),
Expand All @@ -49,7 +49,7 @@ fn sign_verify() -> TestResult {

// priv key template
let priv_key_template = vec![
Attribute::Token(true),
Attribute::Token(false),
Attribute::Private(true),
Attribute::Sign(true),
Attribute::Label(label.to_vec()),
Expand All @@ -76,3 +76,42 @@ fn sign_verify() -> TestResult {

Ok(())
}

#[test]
#[serial]
fn test_import() -> TestResult {
let (pkcs11, slot) = init_pins();

// open a session
let session = pkcs11.open_rw_session(slot)?;

// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;

let mut rng = rand::thread_rng();
let private = p256::ecdsa::SigningKey::random(&mut rng);

let label = b"demo-import";

let template = vec![Attribute::Token(false), Attribute::Label(label.to_vec())];

let private_handle = private.put_key(&session, template.clone())?;
let public_handle = private.verifying_key().put_key(&session, template)?;

// data to sign
let data = [0xFF, 0x55, 0xDD];

let signer =
ecdsa::Signer::<p256::NistP256, _>::new(&session, label).expect("Lookup keys from HSM");

let signature: p256::ecdsa::Signature = signer.sign(&data);

let verifying_key = private.verifying_key();
verifying_key.verify(&data, &signature)?;

// delete keys
session.destroy_object(private_handle)?;
session.destroy_object(public_handle)?;

Ok(())
}

0 comments on commit b1de50d

Please sign in to comment.