Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support ECDSA_P384_SHA384 #64

Merged
merged 1 commit into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions implementations/hostcalls/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ p256 = { version = "0.11.1", features = [
"pkcs8",
"pem",
] }
p384 = { version = "0.11.1", features = [
"ecdsa",
"std",
"pkcs8",
"pem",
] }
pqcrypto = { version = "0.15.0", default-features = false, features = [
"pqcrypto-kyber",
], optional = true }
Expand Down
125 changes: 115 additions & 10 deletions implementations/hostcalls/rust/src/signatures/ecdsa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ::sha2::{Digest, Sha256};
use ::sha2::{Digest, Sha256, Sha384};
use k256::ecdsa::{
self as ecdsa_k256, signature::DigestVerifier as _, signature::RandomizedDigestSigner as _,
};
Expand All @@ -13,6 +13,11 @@ use p256::elliptic_curve::sec1::ToEncodedPoint as _;
use p256::pkcs8::{
DecodePrivateKey as _, DecodePublicKey as _, EncodePrivateKey as _, EncodePublicKey as _,
};
use p384::ecdsa::{
self as ecdsa_p384, signature::DigestVerifier as _, signature::RandomizedDigestSigner as _,
};
use p384::elliptic_curve::sec1::ToEncodedPoint as _;
use p384::pkcs8::{DecodePrivateKey as _, EncodePrivateKey as _, EncodePublicKey as _, DecodePublicKey as _};
use std::convert::TryFrom;
use std::sync::Arc;

Expand All @@ -30,6 +35,7 @@ pub struct EcdsaSignatureSecretKey {
enum EcdsaSigningKeyVariant {
P256(ecdsa_p256::SigningKey),
K256(ecdsa_k256::SigningKey),
P384(ecdsa_p384::SigningKey),
}

#[derive(Clone, Derivative)]
Expand All @@ -53,6 +59,11 @@ impl EcdsaSignatureKeyPair {
ecdsa_k256::SigningKey::from_bytes(raw).map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk =
ecdsa_p384::SigningKey::from_bytes(raw).map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
Ok(EcdsaSignatureKeyPair {
Expand All @@ -68,6 +79,11 @@ impl EcdsaSignatureKeyPair {
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::SigningKey::from_pkcs8_der(pkcs8)
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
Ok(EcdsaSignatureKeyPair {
Expand All @@ -85,6 +101,13 @@ impl EcdsaSignatureKeyPair {
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::SigningKey::from_pkcs8_pem(
std::str::from_utf8(pem).map_err(|_| CryptoError::InvalidKey)?,
)
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaSigningKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
Ok(EcdsaSignatureKeyPair {
Expand All @@ -97,6 +120,7 @@ impl EcdsaSignatureKeyPair {
let raw = match self.ctx.as_ref() {
EcdsaSigningKeyVariant::P256(x) => x.to_bytes().to_vec(),
EcdsaSigningKeyVariant::K256(x) => x.to_bytes().to_vec(),
EcdsaSigningKeyVariant::P384(x) => x.to_bytes().to_vec(),
};
Ok(raw)
}
Expand All @@ -115,6 +139,10 @@ impl EcdsaSignatureKeyPair {
let ecdsa_sk = ecdsa_k256::SigningKey::random(&mut rng);
Self::from_raw(alg, ecdsa_sk.to_bytes().as_slice())
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::SigningKey::random(&mut rng);
Self::from_raw(alg, ecdsa_sk.to_bytes().as_slice())
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
}
}
Expand Down Expand Up @@ -149,6 +177,7 @@ impl EcdsaSignatureKeyPair {
let ctx = match self.ctx.as_ref() {
EcdsaSigningKeyVariant::P256(x) => EcdsaVerifyingKeyVariant::P256(x.verifying_key()),
EcdsaSigningKeyVariant::K256(x) => EcdsaVerifyingKeyVariant::K256(x.verifying_key()),
EcdsaSigningKeyVariant::P384(x) => EcdsaVerifyingKeyVariant::P384(x.verifying_key()),
};
Ok(EcdsaSignaturePublicKey {
alg: self.alg,
Expand All @@ -161,6 +190,7 @@ impl EcdsaSignatureKeyPair {
#[derive(Debug)]
enum HashVariant {
Sha256(Sha256),
Sha384(Sha384),
}

#[derive(Debug)]
Expand All @@ -182,7 +212,7 @@ impl EcdsaSignature {
pub fn from_raw(alg: SignatureAlgorithm, raw: &[u8]) -> Result<Self, CryptoError> {
let expected_len = match alg {
SignatureAlgorithm::ECDSA_P256_SHA256 => 64,
SignatureAlgorithm::ECDSA_K256_SHA256 => 96,
SignatureAlgorithm::ECDSA_K256_SHA256 | SignatureAlgorithm::ECDSA_P384_SHA384 => 96,
_ => bail!(CryptoError::InvalidSignature),
};
ensure!(raw.len() == expected_len, CryptoError::InvalidSignature);
Expand All @@ -202,7 +232,14 @@ impl SignatureLike for EcdsaSignature {

impl EcdsaSignatureState {
pub fn new(kp: EcdsaSignatureKeyPair) -> Self {
let h = HashVariant::Sha256(Sha256::new());
let h = match kp.alg {
SignatureAlgorithm::ECDSA_P384_SHA384 => {
HashVariant::Sha384(Sha384::new())
}
_ => {
HashVariant::Sha256(Sha256::new())
}
};
EcdsaSignatureState { kp, h }
}
}
Expand All @@ -211,26 +248,47 @@ impl SignatureStateLike for EcdsaSignatureState {
fn update(&mut self, input: &[u8]) -> Result<(), CryptoError> {
match &mut self.h {
HashVariant::Sha256(x) => x.update(input),
HashVariant::Sha384(x) => x.update(input),
};
Ok(())
}

fn sign(&mut self) -> Result<Signature, CryptoError> {
let mut rng = SecureRandom::new();
let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
};
let encoded_signature = match self.kp.ctx.as_ref() {
EcdsaSigningKeyVariant::P256(x) => {
let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
let encoded_signature: ecdsa_p256::Signature =
x.sign_digest_with_rng(&mut rng, digest);
encoded_signature.as_ref().to_vec()
}
EcdsaSigningKeyVariant::K256(x) => {
let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
let encoded_signature: ecdsa_k256::Signature =
x.sign_digest_with_rng(&mut rng, digest);
encoded_signature.as_ref().to_vec()
}
EcdsaSigningKeyVariant::P384(x) => {
let digest = match &self.h {
HashVariant::Sha384(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
let encoded_signature: ecdsa_p384::Signature =
x.sign_digest_with_rng(&mut rng, digest);
encoded_signature.as_ref().to_vec()
}
};
let signature = EcdsaSignature::new(encoded_signature);
Ok(Signature::new(Box::new(signature)))
Expand All @@ -245,7 +303,14 @@ pub struct EcdsaSignatureVerificationState {

impl EcdsaSignatureVerificationState {
pub fn new(pk: EcdsaSignaturePublicKey) -> Self {
let h = HashVariant::Sha256(Sha256::new());
let h = match pk.alg {
SignatureAlgorithm::ECDSA_P384_SHA384 => {
HashVariant::Sha384(Sha384::new())
}
_ => {
HashVariant::Sha256(Sha256::new())
}
};
EcdsaSignatureVerificationState { pk, h }
}
}
Expand All @@ -254,6 +319,7 @@ impl SignatureVerificationStateLike for EcdsaSignatureVerificationState {
fn update(&mut self, input: &[u8]) -> Result<(), CryptoError> {
match &mut self.h {
HashVariant::Sha256(x) => x.update(input),
HashVariant::Sha384(x) => x.update(input),
};
Ok(())
}
Expand All @@ -265,18 +331,38 @@ impl SignatureVerificationStateLike for EcdsaSignatureVerificationState {
.downcast_ref::<EcdsaSignature>()
.ok_or(CryptoError::InvalidSignature)?;

let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
};
match self.pk.ctx.as_ref() {
EcdsaVerifyingKeyVariant::P256(x) => {
let ecdsa_signature = ecdsa_p256::Signature::try_from(signature.as_ref())
.map_err(|_| CryptoError::VerificationFailed)?;
let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
x.verify_digest(digest, &ecdsa_signature)
}
EcdsaVerifyingKeyVariant::K256(x) => {
let ecdsa_signature = ecdsa_k256::Signature::try_from(signature.as_ref())
.map_err(|_| CryptoError::VerificationFailed)?;
let digest = match &self.h {
HashVariant::Sha256(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
x.verify_digest(digest, &ecdsa_signature)
}
EcdsaVerifyingKeyVariant::P384(x) => {
let ecdsa_signature = ecdsa_p384::Signature::try_from(signature.as_ref())
.map_err(|_| CryptoError::VerificationFailed)?;
let digest = match &self.h {
HashVariant::Sha384(x) => x.clone(),
_ => {
bail!(CryptoError::UnsupportedAlgorithm)
},
};
x.verify_digest(digest, &ecdsa_signature)
}
}
Expand All @@ -288,6 +374,7 @@ impl SignatureVerificationStateLike for EcdsaSignatureVerificationState {
enum EcdsaVerifyingKeyVariant {
P256(ecdsa_p256::VerifyingKey),
K256(ecdsa_k256::VerifyingKey),
P384(ecdsa_p384::VerifyingKey),
}

#[derive(Clone, Derivative)]
Expand All @@ -311,6 +398,11 @@ impl EcdsaSignaturePublicKey {
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::VerifyingKey::from_sec1_bytes(sec)
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
let pk = EcdsaSignaturePublicKey {
Expand All @@ -327,6 +419,11 @@ impl EcdsaSignaturePublicKey {
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::VerifyingKey::from_public_key_der(pkcs8)
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
let pk = EcdsaSignaturePublicKey {
Expand All @@ -345,6 +442,13 @@ impl EcdsaSignaturePublicKey {
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::K256(ecdsa_sk)
}
SignatureAlgorithm::ECDSA_P384_SHA384 => {
let ecdsa_sk = ecdsa_p384::VerifyingKey::from_public_key_pem(
std::str::from_utf8(pem).map_err(|_| CryptoError::InvalidKey)?,
)
.map_err(|_| CryptoError::InvalidKey)?;
EcdsaVerifyingKeyVariant::P384(ecdsa_sk)
}
_ => bail!(CryptoError::UnsupportedAlgorithm),
};
let pk = EcdsaSignaturePublicKey {
Expand All @@ -362,6 +466,7 @@ impl EcdsaSignaturePublicKey {
let raw = match self.ctx.as_ref() {
EcdsaVerifyingKeyVariant::P256(x) => x.to_encoded_point(compress).to_bytes().to_vec(),
EcdsaVerifyingKeyVariant::K256(x) => x.to_encoded_point(compress).to_bytes().to_vec(),
EcdsaVerifyingKeyVariant::P384(x) => x.to_encoded_point(compress).to_bytes().to_vec(),
};
Ok(raw)
}
Expand Down
4 changes: 3 additions & 1 deletion implementations/hostcalls/rust/src/signatures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::convert::TryFrom;
pub enum SignatureAlgorithm {
ECDSA_P256_SHA256,
ECDSA_K256_SHA256,
ECDSA_P384_SHA384,
Ed25519,
RSA_PKCS1_2048_SHA256,
RSA_PKCS1_2048_SHA384,
Expand All @@ -46,7 +47,7 @@ pub enum SignatureAlgorithmFamily {
impl SignatureAlgorithm {
pub fn family(&self) -> SignatureAlgorithmFamily {
match self {
SignatureAlgorithm::ECDSA_P256_SHA256 | SignatureAlgorithm::ECDSA_K256_SHA256 => {
SignatureAlgorithm::ECDSA_P256_SHA256 | SignatureAlgorithm::ECDSA_K256_SHA256 | SignatureAlgorithm::ECDSA_P384_SHA384 => {
SignatureAlgorithmFamily::ECDSA
}
SignatureAlgorithm::Ed25519 => SignatureAlgorithmFamily::EdDSA,
Expand All @@ -73,6 +74,7 @@ impl TryFrom<&str> for SignatureAlgorithm {
match alg_str.to_uppercase().as_str() {
"ECDSA_P256_SHA256" => Ok(SignatureAlgorithm::ECDSA_P256_SHA256),
"ECDSA_K256_SHA256" => Ok(SignatureAlgorithm::ECDSA_K256_SHA256),
"ECDSA_P384_SHA384" => Ok(SignatureAlgorithm::ECDSA_P384_SHA384),

"ED25519" => Ok(SignatureAlgorithm::Ed25519),

Expand Down