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

[DRAFT] ML-DSA signing and key generation #677

Closed
wants to merge 6 commits into from
Closed
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
2 changes: 1 addition & 1 deletion aws-lc-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fips = ["dep:aws-lc-fips-sys"]

[dependencies]
untrusted = { version = "0.7.1", optional = true }
aws-lc-sys = { version = "0.25.0", path = "../aws-lc-sys", optional = true }
aws-lc-sys = { version = "0.26.0", path = "../aws-lc-sys", optional = true }
aws-lc-fips-sys = { version = "0.13.1", path = "../aws-lc-fips-sys", optional = true }
zeroize = "1.7"
paste = "1.0.11"
Expand Down
22 changes: 4 additions & 18 deletions aws-lc-rs/src/agreement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ use crate::ptr::ConstPointer;
pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey};

use crate::aws_lc::{
EVP_PKEY_CTX_new_id, EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer,
EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1,
NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519,
EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY,
NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519,
};

use crate::buffer::Buffer;
Expand All @@ -74,6 +73,7 @@ use crate::encoding::{
AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der,
EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der,
};
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
use crate::fips::indicator_check;
use crate::ptr::LcPtr;
use core::fmt;
Expand Down Expand Up @@ -482,21 +482,7 @@ impl AsBigEndian<Curve25519SeedBin<'static>> for PrivateKey {
}

pub(crate) fn generate_x25519() -> Result<LcPtr<EVP_PKEY>, Unspecified> {
let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, null_mut()) })?;

if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } {
return Err(Unspecified);
}

let mut pkey: *mut EVP_PKEY = null_mut();

if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) {
return Err(Unspecified);
}

let pkey = LcPtr::new(pkey)?;

Ok(pkey)
LcPtr::<EVP_PKEY>::generate(EVP_PKEY_X25519, No_EVP_PKEY_CTX_consumer)
}

const MAX_PUBLIC_KEY_LEN: usize = ec::PUBLIC_KEY_MAX_LEN;
Expand Down
6 changes: 1 addition & 5 deletions aws-lc-rs/src/bn.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

use crate::aws_lc::{BN_bin2bn, BN_bn2bin, BN_new, BN_num_bits, BN_num_bytes, BN_set_u64, BIGNUM};
use crate::aws_lc::{BN_bin2bn, BN_bn2bin, BN_new, BN_num_bytes, BN_set_u64, BIGNUM};
use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr};
use core::ptr::null_mut;

Expand Down Expand Up @@ -60,8 +60,4 @@ impl ConstPointer<BIGNUM> {
byte_vec
}
}

pub(crate) fn num_bits(&self) -> u32 {
unsafe { BN_num_bits(**self) }
}
}
36 changes: 12 additions & 24 deletions aws-lc-rs/src/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// SPDX-License-Identifier: Apache-2.0 OR ISC

use crate::ec::signature::AlgorithmID;
use core::ptr::null_mut;
// TODO: Uncomment when MSRV >= 1.64
use std::os::raw::c_int;

Expand All @@ -15,12 +14,12 @@ use crate::aws_lc::EC_KEY_check_key;
use crate::aws_lc::{
ECDSA_SIG_from_bytes, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, EC_GROUP_get_curve_name,
EC_KEY_get0_group, EC_group_p224, EC_group_p256, EC_group_p384, EC_group_p521,
EC_group_secp256k1, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid,
EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1,
NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP, EC_KEY, EVP_PKEY,
EVP_PKEY_EC,
EC_group_secp256k1, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_get0_EC_KEY,
NID_X9_62_prime256v1, NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP,
EC_KEY, EVP_PKEY, EVP_PKEY_EC,
};
use crate::error::{KeyRejected, Unspecified};
#[cfg(feature = "fips")]
use crate::fips::indicator_check;
use crate::ptr::{ConstPointer, LcPtr};
use crate::signature::Signature;
Expand Down Expand Up @@ -85,25 +84,14 @@ pub(crate) fn validate_evp_key(

#[inline]
pub(crate) fn evp_key_generate(nid: c_int) -> Result<LcPtr<EVP_PKEY>, Unspecified> {
let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_EC, null_mut()) })?;

if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } {
return Err(Unspecified);
}

if 1 != unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(*pkey_ctx.as_mut(), nid) } {
return Err(Unspecified);
}

let mut pkey = null_mut::<EVP_PKEY>();

if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) {
return Err(Unspecified);
}

let pkey = LcPtr::new(pkey)?;

Ok(pkey)
let params_fn = |ctx| {
if 1 == unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) } {
Ok(())
} else {
Err(())
}
};
LcPtr::<EVP_PKEY>::generate(EVP_PKEY_EC, Some(params_fn))
}

#[inline]
Expand Down
83 changes: 10 additions & 73 deletions aws-lc-rs/src/ec/key_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,28 @@

use core::fmt;
use core::fmt::{Debug, Formatter};
use core::mem::MaybeUninit;
use core::ptr::{null, null_mut};

use crate::aws_lc::{EVP_DigestSign, EVP_DigestSignInit, EVP_PKEY_cmp, EVP_PKEY, EVP_PKEY_EC};
use crate::aws_lc::{EVP_PKEY_cmp, EVP_PKEY, EVP_PKEY_EC};

use crate::digest::digest_ctx::DigestContext;
use crate::ec::evp_key_generate;
use crate::ec::signature::{EcdsaSignatureFormat, EcdsaSigningAlgorithm, PublicKey};
#[cfg(feature = "fips")]
use crate::ec::validate_evp_key;
#[cfg(not(feature = "fips"))]
use crate::ec::verify_evp_key_nid;

use crate::ec;
use crate::ec::encoding::rfc5915::{marshal_rfc5915_private_key, parse_rfc5915_private_key};
use crate::ec::encoding::sec1::{
marshal_sec1_private_key, parse_sec1_private_bn, parse_sec1_public_point,
};
use crate::encoding::{AsBigEndian, AsDer, EcPrivateKeyBin, EcPrivateKeyRfc5915Der};
use crate::error::{KeyRejected, Unspecified};
use crate::fips::indicator_check;
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
use crate::pkcs8::{Document, Version};
use crate::ptr::LcPtr;
use crate::rand::SecureRandom;
use crate::signature::{KeyPair, Signature};
use crate::{digest, ec};

/// An ECDSA key pair, used for signing.
#[allow(clippy::module_name_repetitions)]
Expand Down Expand Up @@ -212,82 +209,22 @@ impl EcdsaKeyPair {
// * Digest Algorithms: SHA256, SHA384, SHA512
#[inline]
pub fn sign(&self, _rng: &dyn SecureRandom, message: &[u8]) -> Result<Signature, Unspecified> {
let mut md_ctx = DigestContext::new_uninit();

let digest = digest::match_digest_type(&self.algorithm.digest.id);

if 1 != unsafe {
// EVP_DigestSignInit does not mutate |pkey| for thread-safety purposes and may be
// used concurrently with other non-mutating functions on |pkey|.
// https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L297-L313
EVP_DigestSignInit(
md_ctx.as_mut_ptr(),
null_mut(),
*digest,
null_mut(),
*self.evp_pkey.as_mut_unsafe(),
)
} {
return Err(Unspecified);
}

let mut out_sig = vec![0u8; get_signature_length(&mut md_ctx)?];

let out_sig = compute_ecdsa_signature(&mut md_ctx, message, out_sig.as_mut_slice())?;
let out_sig = self.evp_pkey.sign(
message,
Some(self.algorithm.digest),
No_EVP_PKEY_CTX_consumer,
)?;

Ok(match self.algorithm.sig_format {
EcdsaSignatureFormat::ASN1 => Signature::new(|slice| {
slice[..out_sig.len()].copy_from_slice(out_sig);
slice[..out_sig.len()].copy_from_slice(&out_sig);
out_sig.len()
}),
EcdsaSignatureFormat::Fixed => ec::ecdsa_asn1_to_fixed(self.algorithm.id, out_sig)?,
EcdsaSignatureFormat::Fixed => ec::ecdsa_asn1_to_fixed(self.algorithm.id, &out_sig)?,
})
}
}

#[inline]
fn get_signature_length(ctx: &mut DigestContext) -> Result<usize, Unspecified> {
let mut out_sig_len = MaybeUninit::<usize>::uninit();

// determine signature size
if 1 != unsafe {
EVP_DigestSign(
ctx.as_mut_ptr(),
null_mut(),
out_sig_len.as_mut_ptr(),
null(),
0,
)
} {
return Err(Unspecified);
}

Ok(unsafe { out_sig_len.assume_init() })
}

#[inline]
fn compute_ecdsa_signature<'a>(
ctx: &mut DigestContext,
message: &[u8],
signature: &'a mut [u8],
) -> Result<&'a mut [u8], Unspecified> {
let mut out_sig_len = signature.len();

if 1 != indicator_check!(unsafe {
EVP_DigestSign(
ctx.as_mut_ptr(),
signature.as_mut_ptr(),
&mut out_sig_len,
message.as_ptr(),
message.len(),
)
}) {
return Err(Unspecified);
}

Ok(&mut signature[0..out_sig_len])
}

/// Elliptic curve private key.
pub struct PrivateKey<'a>(&'a EcdsaKeyPair);

Expand Down
40 changes: 5 additions & 35 deletions aws-lc-rs/src/ec/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@
// SPDX-License-Identifier: Apache-2.0 OR ISC

use crate::aws_lc::{
ECDSA_SIG_new, ECDSA_SIG_set0, ECDSA_SIG_to_bytes, EVP_DigestVerify, EVP_DigestVerifyInit,
NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, BIGNUM, ECDSA_SIG, EVP_PKEY,
ECDSA_SIG_new, ECDSA_SIG_set0, ECDSA_SIG_to_bytes, NID_X9_62_prime256v1, NID_secp256k1,
NID_secp384r1, NID_secp521r1, BIGNUM, ECDSA_SIG, EVP_PKEY,
};

use crate::digest::digest_ctx::DigestContext;
use crate::ec::compressed_public_key_size_bytes;
use crate::ec::encoding::parse_ec_public_key;
use crate::ec::encoding::sec1::marshal_sec1_public_point;
use crate::encoding::{
AsBigEndian, AsDer, EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der,
};
use crate::error::Unspecified;
use crate::fips::indicator_check;
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
use crate::ptr::{DetachableLcPtr, LcPtr};
use crate::signature::VerificationAlgorithm;
use crate::{digest, sealed};
Expand Down Expand Up @@ -232,37 +231,8 @@ fn verify_asn1_signature(
msg: &[u8],
signature: &[u8],
) -> Result<(), Unspecified> {
let mut pkey = parse_ec_public_key(public_key, alg.nid())?;

let mut md_ctx = DigestContext::new_uninit();

let digest = digest::match_digest_type(&digest.id);

if 1 != unsafe {
EVP_DigestVerifyInit(
md_ctx.as_mut_ptr(),
null_mut(),
*digest,
null_mut(),
*pkey.as_mut(),
)
} {
return Err(Unspecified);
}

if 1 != indicator_check!(unsafe {
EVP_DigestVerify(
md_ctx.as_mut_ptr(),
signature.as_ptr(),
signature.len(),
msg.as_ptr(),
msg.len(),
)
}) {
return Err(Unspecified);
}

Ok(())
let evp_pkey = parse_ec_public_key(public_key, alg.nid())?;
evp_pkey.verify(msg, Some(digest), No_EVP_PKEY_CTX_consumer, signature)
}

#[inline]
Expand Down
Loading
Loading