Skip to content

Commit 30e1d77

Browse files
committed
Add helpers to read public keys
Signed-off-by: Arthur Gautier <baloo@superbaloo.net>
1 parent 230120d commit 30e1d77

File tree

4 files changed

+109
-71
lines changed

4 files changed

+109
-71
lines changed

cryptoki-rustcrypto/src/ecdsa.rs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,46 @@ use thiserror::Error;
2929

3030
use crate::SessionLike;
3131

32+
pub fn read_key<S: SessionLike, C: SignAlgorithm>(
33+
session: &S,
34+
template: impl Into<Vec<Attribute>>,
35+
) -> Result<PublicKey<C>, Error>
36+
where
37+
FieldBytesSize<C>: ModulusSize,
38+
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
39+
{
40+
let mut template = template.into();
41+
template.push(Attribute::Class(ObjectClass::PUBLIC_KEY));
42+
template.push(Attribute::KeyType(KeyType::EC));
43+
template.push(Attribute::EcParams(C::OID.to_der().unwrap()));
44+
45+
let keys = session.find_objects(&template)?;
46+
if let Some(public_key) = keys.first() {
47+
let attribute_pk = session.get_attributes(*public_key, &[AttributeType::EcPoint])?;
48+
49+
let mut ec_point = None;
50+
for attribute in attribute_pk {
51+
match attribute {
52+
Attribute::EcPoint(p) if ec_point.is_none() => {
53+
ec_point = Some(p);
54+
}
55+
_ => {}
56+
}
57+
}
58+
59+
let ec_point = ec_point.ok_or(Error::MissingAttribute(AttributeType::EcPoint))?;
60+
61+
// documented as "DER-encoding of ANSI X9.62 ECPoint value Q"
62+
// https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/pkcs11-spec-v3.1-os.html#_Toc111203418
63+
// https://www.rfc-editor.org/rfc/rfc5480#section-2.2
64+
let ec_point = OctetStringRef::from_der(&ec_point).unwrap();
65+
66+
Ok(PublicKey::<C>::from_sec1_bytes(ec_point.as_bytes())?)
67+
} else {
68+
Err(Error::MissingKey)
69+
}
70+
}
71+
3272
#[derive(Error, Debug)]
3373
pub enum Error {
3474
#[error("Cryptoki error: {0}")]
@@ -39,6 +79,9 @@ pub enum Error {
3979

4080
#[error("Elliptic curve error: {0}")]
4181
Ecdsa(#[from] ecdsa::elliptic_curve::Error),
82+
83+
#[error("Key not found")]
84+
MissingKey,
4285
}
4386

4487
pub trait SignAlgorithm: PrimeCurve + CurveArithmetic + AssociatedOid + DigestPrimitive {
@@ -53,7 +96,6 @@ impl SignAlgorithm for p256::NistP256 {
5396

5497
pub struct Signer<C: SignAlgorithm, S: SessionLike> {
5598
session: S,
56-
_public_key: ObjectHandle,
5799
private_key: ObjectHandle,
58100
verifying_key: VerifyingKey<C>,
59101
}
@@ -79,13 +121,7 @@ where
79121
let attribute_pk = session.get_attributes(private_key, &[AttributeType::Id])?;
80122

81123
// Second we'll lookup a public key with the same label/ec params/ec point
82-
let mut template = vec![
83-
Attribute::Private(false),
84-
Attribute::Label(label.to_vec()),
85-
Attribute::Class(ObjectClass::PUBLIC_KEY),
86-
Attribute::KeyType(KeyType::EC),
87-
Attribute::EcParams(C::OID.to_der().unwrap()),
88-
];
124+
let mut template = vec![Attribute::Private(false), Attribute::Label(label.to_vec())];
89125
let mut id = None;
90126
for attribute in attribute_pk {
91127
match attribute {
@@ -97,32 +133,14 @@ where
97133
}
98134
}
99135

100-
let public_key = session.find_objects(&template)?.remove(0);
101-
let attribute_pk = session.get_attributes(public_key, &[AttributeType::EcPoint])?;
136+
id.ok_or(Error::MissingAttribute(AttributeType::Id))?;
102137

103-
let mut ec_point = None;
104-
for attribute in attribute_pk {
105-
match attribute {
106-
Attribute::EcPoint(p) if ec_point.is_none() => {
107-
ec_point = Some(p);
108-
}
109-
_ => {}
110-
}
111-
}
112-
113-
let ec_point = ec_point.ok_or(Error::MissingAttribute(AttributeType::EcPoint))?;
114-
115-
// documented as "DER-encoding of ANSI X9.62 ECPoint value Q"
116-
// https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/pkcs11-spec-v3.1-os.html#_Toc111203418
117-
// https://www.rfc-editor.org/rfc/rfc5480#section-2.2
118-
let ec_point = OctetStringRef::from_der(&ec_point).unwrap();
119-
let public = PublicKey::<C>::from_sec1_bytes(ec_point.as_bytes())?;
138+
let public = read_key(&session, template)?;
120139
let verifying_key = public.into();
121140

122141
Ok(Self {
123142
session,
124143
private_key,
125-
_public_key: public_key,
126144
verifying_key,
127145
})
128146
}

cryptoki-rustcrypto/src/rsa/mod.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,67 @@
11
// Copyright 2023 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use cryptoki::mechanism::{
5-
rsa::{PkcsMgfType, PkcsPssParams},
6-
Mechanism, MechanismType,
4+
use cryptoki::{
5+
mechanism::{
6+
rsa::{PkcsMgfType, PkcsPssParams},
7+
Mechanism, MechanismType,
8+
},
9+
object::{Attribute, AttributeType, KeyType, ObjectClass},
710
};
8-
use cryptoki::object::AttributeType;
911
use der::oid::AssociatedOid;
12+
use rsa::{BigUint, RsaPublicKey};
1013
use signature::digest::Digest;
1114
use std::convert::TryInto;
1215
use thiserror::Error;
1316

14-
pub mod pkcs1v15;
17+
use crate::SessionLike;
1518

19+
pub mod pkcs1v15;
1620
pub mod pss;
1721

22+
pub fn read_key<S: SessionLike>(
23+
session: &S,
24+
template: impl Into<Vec<Attribute>>,
25+
) -> Result<RsaPublicKey, Error> {
26+
let mut template: Vec<Attribute> = template.into();
27+
template.push(Attribute::Class(ObjectClass::PUBLIC_KEY));
28+
template.push(Attribute::KeyType(KeyType::RSA));
29+
30+
let keys = session.find_objects(&template)?;
31+
if let Some(key) = keys.first() {
32+
let attribute_pk = session.get_attributes(
33+
*key,
34+
&[AttributeType::Modulus, AttributeType::PublicExponent],
35+
)?;
36+
37+
let mut modulus = None;
38+
let mut public_exponent = None;
39+
40+
for attribute in attribute_pk {
41+
match attribute {
42+
Attribute::Modulus(m) if modulus.is_none() => {
43+
modulus = Some(m.clone());
44+
}
45+
Attribute::PublicExponent(e) if public_exponent.is_none() => {
46+
public_exponent = Some(e.clone());
47+
}
48+
_ => {}
49+
}
50+
}
51+
52+
let modulus = modulus
53+
.ok_or(Error::MissingAttribute(AttributeType::Modulus))
54+
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
55+
let public_exponent = public_exponent
56+
.ok_or(Error::MissingAttribute(AttributeType::PublicExponent))
57+
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
58+
59+
Ok(RsaPublicKey::new(modulus, public_exponent)?)
60+
} else {
61+
Err(Error::MissingKey)
62+
}
63+
}
64+
1865
#[derive(Debug, Error)]
1966
pub enum Error {
2067
#[error("Cryptoki error: {0}")]
@@ -25,6 +72,9 @@ pub enum Error {
2572

2673
#[error("RSA error: {0}")]
2774
Rsa(#[from] rsa::Error),
75+
76+
#[error("Key not found")]
77+
MissingKey,
2878
}
2979

3080
pub trait DigestSigning: Digest + AssociatedOid {

cryptoki-rustcrypto/src/rsa/pkcs1v15.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ use der::AnyRef;
66
use rsa::{
77
pkcs1,
88
pkcs1v15::{Signature, VerifyingKey},
9-
BigUint, RsaPublicKey,
109
};
1110
use spki::{AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier};
1211
use std::convert::TryFrom;
1312

14-
use super::{DigestSigning, Error};
13+
use super::{read_key, DigestSigning, Error};
1514
use crate::SessionLike;
1615

1716
pub struct Signer<D: DigestSigning, S: SessionLike> {
1817
session: S,
19-
_public_key: ObjectHandle,
2018
private_key: ObjectHandle,
2119
verifying_key: VerifyingKey<D>,
2220
}
@@ -40,12 +38,7 @@ impl<D: DigestSigning, S: SessionLike> Signer<D, S> {
4038
)?;
4139

4240
// Second we'll lookup a public key with the same label/modulus/public exponent
43-
let mut template = vec![
44-
Attribute::Private(false),
45-
Attribute::Label(label.to_vec()),
46-
Attribute::Class(ObjectClass::PUBLIC_KEY),
47-
Attribute::KeyType(KeyType::RSA),
48-
];
41+
let mut template = vec![Attribute::Private(false), Attribute::Label(label.to_vec())];
4942
let mut modulus = None;
5043
let mut public_exponent = None;
5144
for attribute in attribute_pk {
@@ -62,21 +55,13 @@ impl<D: DigestSigning, S: SessionLike> Signer<D, S> {
6255
}
6356
}
6457

65-
let modulus = modulus
66-
.ok_or(Error::MissingAttribute(AttributeType::Modulus))
67-
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
68-
let public_exponent = public_exponent
69-
.ok_or(Error::MissingAttribute(AttributeType::PublicExponent))
70-
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
71-
72-
let public_key = session.find_objects(&template)?.remove(0);
58+
let public_key = read_key(&session, template)?;
7359

74-
let verifying_key = VerifyingKey::new(RsaPublicKey::new(modulus, public_exponent)?);
60+
let verifying_key = VerifyingKey::new(public_key);
7561

7662
Ok(Self {
7763
session,
7864
private_key,
79-
_public_key: public_key,
8065
verifying_key,
8166
})
8267
}

cryptoki-rustcrypto/src/rsa/pss.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rsa::{
77
pkcs1::{self, RsaPssParams},
88
pkcs8::{self},
99
pss::{Signature, VerifyingKey},
10-
BigUint, RsaPublicKey,
1110
};
1211
use signature::digest::Digest;
1312
use spki::{
@@ -16,12 +15,11 @@ use spki::{
1615
};
1716
use std::convert::TryFrom;
1817

19-
use super::{DigestSigning, Error};
18+
use super::{read_key, DigestSigning, Error};
2019
use crate::SessionLike;
2120

2221
pub struct Signer<D: DigestSigning, S: SessionLike> {
2322
session: S,
24-
_public_key: ObjectHandle,
2523
private_key: ObjectHandle,
2624
verifying_key: VerifyingKey<D>,
2725
salt_len: usize,
@@ -46,12 +44,7 @@ impl<D: DigestSigning, S: SessionLike> Signer<D, S> {
4644
)?;
4745

4846
// Second we'll lookup a public key with the same label/modulus/public exponent
49-
let mut template = vec![
50-
Attribute::Private(false),
51-
Attribute::Label(label.to_vec()),
52-
Attribute::Class(ObjectClass::PUBLIC_KEY),
53-
Attribute::KeyType(KeyType::RSA),
54-
];
47+
let mut template = vec![Attribute::Private(false), Attribute::Label(label.to_vec())];
5548
let mut modulus = None;
5649
let mut public_exponent = None;
5750
for attribute in attribute_pk {
@@ -68,22 +61,14 @@ impl<D: DigestSigning, S: SessionLike> Signer<D, S> {
6861
}
6962
}
7063

71-
let modulus = modulus
72-
.ok_or(Error::MissingAttribute(AttributeType::Modulus))
73-
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
74-
let public_exponent = public_exponent
75-
.ok_or(Error::MissingAttribute(AttributeType::PublicExponent))
76-
.map(|v| BigUint::from_bytes_be(v.as_slice()))?;
77-
78-
let public_key = session.find_objects(&template)?.remove(0);
64+
let public_key = read_key(&session, template)?;
7965

80-
let verifying_key = VerifyingKey::new(RsaPublicKey::new(modulus, public_exponent)?);
66+
let verifying_key = VerifyingKey::new(public_key);
8167
let salt_len = <D as Digest>::output_size();
8268

8369
Ok(Self {
8470
session,
8571
private_key,
86-
_public_key: public_key,
8772
verifying_key,
8873
salt_len,
8974
})

0 commit comments

Comments
 (0)