Skip to content

Commit 33614e2

Browse files
authored
EVP_PKEY refactoring for keygen/sign/verify; Start of ML-DSA impl (#689)
* Generation/Serialization for ML-DSA * Support sign/verify for EVP_PKEY * Consolidate EVP_DigestSign/EVP_DigestVerify usage * Consolidate EVP_PKEY_keygen usage * Satisfy clippy
1 parent 5af71cc commit 33614e2

15 files changed

+431
-440
lines changed

aws-lc-rs/src/agreement.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@ use crate::ptr::ConstPointer;
6262
pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey};
6363

6464
use crate::aws_lc::{
65-
EVP_PKEY_CTX_new_id, EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer,
66-
EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1,
67-
NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519,
65+
EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY,
66+
NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519,
6867
};
6968

7069
use crate::buffer::Buffer;
@@ -74,6 +73,7 @@ use crate::encoding::{
7473
AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der,
7574
EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der,
7675
};
76+
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
7777
use crate::fips::indicator_check;
7878
use crate::ptr::LcPtr;
7979
use core::fmt;
@@ -482,21 +482,7 @@ impl AsBigEndian<Curve25519SeedBin<'static>> for PrivateKey {
482482
}
483483

484484
pub(crate) fn generate_x25519() -> Result<LcPtr<EVP_PKEY>, Unspecified> {
485-
let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, null_mut()) })?;
486-
487-
if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } {
488-
return Err(Unspecified);
489-
}
490-
491-
let mut pkey: *mut EVP_PKEY = null_mut();
492-
493-
if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) {
494-
return Err(Unspecified);
495-
}
496-
497-
let pkey = LcPtr::new(pkey)?;
498-
499-
Ok(pkey)
485+
LcPtr::<EVP_PKEY>::generate(EVP_PKEY_X25519, No_EVP_PKEY_CTX_consumer)
500486
}
501487

502488
const MAX_PUBLIC_KEY_LEN: usize = ec::PUBLIC_KEY_MAX_LEN;

aws-lc-rs/src/bn.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0 OR ISC
33

4-
use crate::aws_lc::{BN_bin2bn, BN_bn2bin, BN_new, BN_num_bits, BN_num_bytes, BN_set_u64, BIGNUM};
4+
use crate::aws_lc::{BN_bin2bn, BN_bn2bin, BN_new, BN_num_bytes, BN_set_u64, BIGNUM};
55
use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr};
66
use core::ptr::null_mut;
77

@@ -60,8 +60,4 @@ impl ConstPointer<BIGNUM> {
6060
byte_vec
6161
}
6262
}
63-
64-
pub(crate) fn num_bits(&self) -> u32 {
65-
unsafe { BN_num_bits(**self) }
66-
}
6763
}

aws-lc-rs/src/ec.rs

+12-24
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// SPDX-License-Identifier: Apache-2.0 OR ISC
55

66
use crate::ec::signature::AlgorithmID;
7-
use core::ptr::null_mut;
87
// TODO: Uncomment when MSRV >= 1.64
98
use std::os::raw::c_int;
109

@@ -15,12 +14,12 @@ use crate::aws_lc::EC_KEY_check_key;
1514
use crate::aws_lc::{
1615
ECDSA_SIG_from_bytes, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, EC_GROUP_get_curve_name,
1716
EC_KEY_get0_group, EC_group_p224, EC_group_p256, EC_group_p384, EC_group_p521,
18-
EC_group_secp256k1, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid,
19-
EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1,
20-
NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP, EC_KEY, EVP_PKEY,
21-
EVP_PKEY_EC,
17+
EC_group_secp256k1, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_get0_EC_KEY,
18+
NID_X9_62_prime256v1, NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP,
19+
EC_KEY, EVP_PKEY, EVP_PKEY_EC,
2220
};
2321
use crate::error::{KeyRejected, Unspecified};
22+
#[cfg(feature = "fips")]
2423
use crate::fips::indicator_check;
2524
use crate::ptr::{ConstPointer, LcPtr};
2625
use crate::signature::Signature;
@@ -85,25 +84,14 @@ pub(crate) fn validate_evp_key(
8584

8685
#[inline]
8786
pub(crate) fn evp_key_generate(nid: c_int) -> Result<LcPtr<EVP_PKEY>, Unspecified> {
88-
let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_EC, null_mut()) })?;
89-
90-
if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } {
91-
return Err(Unspecified);
92-
}
93-
94-
if 1 != unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(*pkey_ctx.as_mut(), nid) } {
95-
return Err(Unspecified);
96-
}
97-
98-
let mut pkey = null_mut::<EVP_PKEY>();
99-
100-
if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) {
101-
return Err(Unspecified);
102-
}
103-
104-
let pkey = LcPtr::new(pkey)?;
105-
106-
Ok(pkey)
87+
let params_fn = |ctx| {
88+
if 1 == unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) } {
89+
Ok(())
90+
} else {
91+
Err(())
92+
}
93+
};
94+
LcPtr::<EVP_PKEY>::generate(EVP_PKEY_EC, Some(params_fn))
10795
}
10896

10997
#[inline]

aws-lc-rs/src/ec/key_pair.rs

+10-73
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,29 @@
33
// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
44
// SPDX-License-Identifier: Apache-2.0 OR ISC
55

6-
use crate::aws_lc::{EVP_DigestSign, EVP_DigestSignInit, EVP_PKEY, EVP_PKEY_EC};
6+
use crate::aws_lc::{EVP_PKEY, EVP_PKEY_EC};
77
use core::fmt;
88
use core::fmt::{Debug, Formatter};
9-
use core::mem::MaybeUninit;
10-
use core::ptr::{null, null_mut};
119

12-
use crate::digest::digest_ctx::DigestContext;
1310
use crate::ec::evp_key_generate;
1411
use crate::ec::signature::{EcdsaSignatureFormat, EcdsaSigningAlgorithm, PublicKey};
1512
#[cfg(feature = "fips")]
1613
use crate::ec::validate_evp_key;
1714
#[cfg(not(feature = "fips"))]
1815
use crate::ec::verify_evp_key_nid;
1916

17+
use crate::ec;
2018
use crate::ec::encoding::rfc5915::{marshal_rfc5915_private_key, parse_rfc5915_private_key};
2119
use crate::ec::encoding::sec1::{
2220
marshal_sec1_private_key, parse_sec1_private_bn, parse_sec1_public_point,
2321
};
2422
use crate::encoding::{AsBigEndian, AsDer, EcPrivateKeyBin, EcPrivateKeyRfc5915Der};
2523
use crate::error::{KeyRejected, Unspecified};
26-
use crate::fips::indicator_check;
24+
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
2725
use crate::pkcs8::{Document, Version};
2826
use crate::ptr::LcPtr;
2927
use crate::rand::SecureRandom;
3028
use crate::signature::{KeyPair, Signature};
31-
use crate::{digest, ec};
3229

3330
/// An ECDSA key pair, used for signing.
3431
#[allow(clippy::module_name_repetitions)]
@@ -212,82 +209,22 @@ impl EcdsaKeyPair {
212209
// * Digest Algorithms: SHA256, SHA384, SHA512
213210
#[inline]
214211
pub fn sign(&self, _rng: &dyn SecureRandom, message: &[u8]) -> Result<Signature, Unspecified> {
215-
let mut md_ctx = DigestContext::new_uninit();
216-
217-
let digest = digest::match_digest_type(&self.algorithm.digest.id);
218-
219-
if 1 != unsafe {
220-
// EVP_DigestSignInit does not mutate |pkey| for thread-safety purposes and may be
221-
// used concurrently with other non-mutating functions on |pkey|.
222-
// https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L297-L313
223-
EVP_DigestSignInit(
224-
md_ctx.as_mut_ptr(),
225-
null_mut(),
226-
*digest,
227-
null_mut(),
228-
*self.evp_pkey.as_mut_unsafe(),
229-
)
230-
} {
231-
return Err(Unspecified);
232-
}
233-
234-
let mut out_sig = vec![0u8; get_signature_length(&mut md_ctx)?];
235-
236-
let out_sig = compute_ecdsa_signature(&mut md_ctx, message, out_sig.as_mut_slice())?;
212+
let out_sig = self.evp_pkey.sign(
213+
message,
214+
Some(self.algorithm.digest),
215+
No_EVP_PKEY_CTX_consumer,
216+
)?;
237217

238218
Ok(match self.algorithm.sig_format {
239219
EcdsaSignatureFormat::ASN1 => Signature::new(|slice| {
240-
slice[..out_sig.len()].copy_from_slice(out_sig);
220+
slice[..out_sig.len()].copy_from_slice(&out_sig);
241221
out_sig.len()
242222
}),
243-
EcdsaSignatureFormat::Fixed => ec::ecdsa_asn1_to_fixed(self.algorithm.id, out_sig)?,
223+
EcdsaSignatureFormat::Fixed => ec::ecdsa_asn1_to_fixed(self.algorithm.id, &out_sig)?,
244224
})
245225
}
246226
}
247227

248-
#[inline]
249-
fn get_signature_length(ctx: &mut DigestContext) -> Result<usize, Unspecified> {
250-
let mut out_sig_len = MaybeUninit::<usize>::uninit();
251-
252-
// determine signature size
253-
if 1 != unsafe {
254-
EVP_DigestSign(
255-
ctx.as_mut_ptr(),
256-
null_mut(),
257-
out_sig_len.as_mut_ptr(),
258-
null(),
259-
0,
260-
)
261-
} {
262-
return Err(Unspecified);
263-
}
264-
265-
Ok(unsafe { out_sig_len.assume_init() })
266-
}
267-
268-
#[inline]
269-
fn compute_ecdsa_signature<'a>(
270-
ctx: &mut DigestContext,
271-
message: &[u8],
272-
signature: &'a mut [u8],
273-
) -> Result<&'a mut [u8], Unspecified> {
274-
let mut out_sig_len = signature.len();
275-
276-
if 1 != indicator_check!(unsafe {
277-
EVP_DigestSign(
278-
ctx.as_mut_ptr(),
279-
signature.as_mut_ptr(),
280-
&mut out_sig_len,
281-
message.as_ptr(),
282-
message.len(),
283-
)
284-
}) {
285-
return Err(Unspecified);
286-
}
287-
288-
Ok(&mut signature[0..out_sig_len])
289-
}
290-
291228
/// Elliptic curve private key.
292229
pub struct PrivateKey<'a>(&'a EcdsaKeyPair);
293230

aws-lc-rs/src/ec/signature.rs

+5-35
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22
// SPDX-License-Identifier: Apache-2.0 OR ISC
33

44
use crate::aws_lc::{
5-
ECDSA_SIG_new, ECDSA_SIG_set0, ECDSA_SIG_to_bytes, EVP_DigestVerify, EVP_DigestVerifyInit,
6-
NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, BIGNUM, ECDSA_SIG, EVP_PKEY,
5+
ECDSA_SIG_new, ECDSA_SIG_set0, ECDSA_SIG_to_bytes, NID_X9_62_prime256v1, NID_secp256k1,
6+
NID_secp384r1, NID_secp521r1, BIGNUM, ECDSA_SIG, EVP_PKEY,
77
};
88

9-
use crate::digest::digest_ctx::DigestContext;
109
use crate::ec::compressed_public_key_size_bytes;
1110
use crate::ec::encoding::parse_ec_public_key;
1211
use crate::ec::encoding::sec1::marshal_sec1_public_point;
1312
use crate::encoding::{
1413
AsBigEndian, AsDer, EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der,
1514
};
1615
use crate::error::Unspecified;
17-
use crate::fips::indicator_check;
16+
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
1817
use crate::ptr::{DetachableLcPtr, LcPtr};
1918
use crate::signature::VerificationAlgorithm;
2019
use crate::{digest, sealed};
@@ -232,37 +231,8 @@ fn verify_asn1_signature(
232231
msg: &[u8],
233232
signature: &[u8],
234233
) -> Result<(), Unspecified> {
235-
let mut pkey = parse_ec_public_key(public_key, alg.nid())?;
236-
237-
let mut md_ctx = DigestContext::new_uninit();
238-
239-
let digest = digest::match_digest_type(&digest.id);
240-
241-
if 1 != unsafe {
242-
EVP_DigestVerifyInit(
243-
md_ctx.as_mut_ptr(),
244-
null_mut(),
245-
*digest,
246-
null_mut(),
247-
*pkey.as_mut(),
248-
)
249-
} {
250-
return Err(Unspecified);
251-
}
252-
253-
if 1 != indicator_check!(unsafe {
254-
EVP_DigestVerify(
255-
md_ctx.as_mut_ptr(),
256-
signature.as_ptr(),
257-
signature.len(),
258-
msg.as_ptr(),
259-
msg.len(),
260-
)
261-
}) {
262-
return Err(Unspecified);
263-
}
264-
265-
Ok(())
234+
let evp_pkey = parse_ec_public_key(public_key, alg.nid())?;
235+
evp_pkey.verify(msg, Some(digest), No_EVP_PKEY_CTX_consumer, signature)
266236
}
267237

268238
#[inline]

0 commit comments

Comments
 (0)