Skip to content

Commit 2e8b158

Browse files
authored
Unstable API for ML-DSA (#690)
* unstable API for ML-DSA * ML-DSA KAT tests * Satisfy clippy * Fix copyright check * PR feedback * Fix latest clippy lints * Remove PqdsaSeed; More cleanup * More clippy; more cleanup * PR feedback
1 parent d998c01 commit 2e8b158

28 files changed

+1128
-180
lines changed

aws-lc-rs/Makefile

+13-7
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,32 @@ coverage:
3030
coverage-fips:
3131
cargo llvm-cov --features "${AWS_LC_RS_COV_EXTRA_FEATURES},fips" --no-fail-fast --fail-under-lines 95 --ignore-filename-regex "aws-lc(-fips|)-sys/*" --lcov --output-path lcov.info
3232

33+
test: export AWS_LC_RS_DISABLE_SLOW_TESTS = 1
3334
test:
35+
cargo test --all-targets
3436
cargo test --all-targets --features unstable
35-
cargo test --release --all-targets
3637
cargo test --release --all-targets --features bindgen,unstable
37-
cargo test --release --all-targets --features fips,unstable
38-
cargo test --no-default-features --all-targets --features fips,unstable
38+
cargo test --release --all-targets --features fips,bindgen,unstable
39+
cargo test --no-default-features --all-targets --features aws-lc-sys
3940
cargo test --no-default-features --all-targets --features aws-lc-sys,unstable
40-
cargo test --no-default-features --all-targets --features aws-lc-sys,ring-sig-verify,unstable
41-
cargo test --no-default-features --all-targets --features aws-lc-sys,ring-io,unstable
42-
cargo test --no-default-features --all-targets --features aws-lc-sys,alloc,unstable
41+
cargo test --no-default-features --all-targets --features fips
42+
cargo test --no-default-features --all-targets --features fips,unstable
43+
cargo test --no-default-features --all-targets --features aws-lc-sys,ring-sig-verify
44+
cargo test --no-default-features --all-targets --features aws-lc-sys,ring-io
45+
cargo test --no-default-features --all-targets --features aws-lc-sys,alloc
4346

4447
msrv:
4548
cargo msrv verify
4649

4750
clippy:
4851
cargo +nightly clippy --all-targets --features bindgen,fips,unstable -- -W clippy::all -W clippy::pedantic
4952

50-
clippy-fix:
53+
clippy-fips-fix:
5154
cargo +nightly clippy --all-targets --features bindgen,fips,unstable --fix --allow-dirty -- -W clippy::all -W clippy::pedantic
5255

56+
clippy-fix:
57+
cargo +nightly clippy --all-targets --features bindgen,unstable --fix --allow-dirty -- -W clippy::all -W clippy::pedantic
58+
5359
ci: format clippy msrv test coverage api-diff-pub
5460

5561
readme:

aws-lc-rs/src/agreement.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use crate::ec::encoding::sec1::{
5656
parse_sec1_private_bn,
5757
};
5858
#[cfg(feature = "fips")]
59-
use crate::ec::validate_evp_key;
59+
use crate::ec::validate_ec_evp_key;
6060
#[cfg(not(feature = "fips"))]
6161
use crate::ec::verify_evp_key_nid;
6262
use crate::ec::{encoding, evp_key_generate};
@@ -304,7 +304,7 @@ impl PrivateKey {
304304
#[cfg(not(feature = "fips"))]
305305
verify_evp_key_nid(&evp_pkey.as_const(), alg.id.nid())?;
306306
#[cfg(feature = "fips")]
307-
validate_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
307+
validate_ec_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
308308

309309
Ok(Self::new(alg, evp_pkey))
310310
}
@@ -333,7 +333,7 @@ impl PrivateKey {
333333
}
334334

335335
#[cfg(test)]
336-
#[allow(clippy::missing_errors_doc, missing_docs)]
336+
#[allow(missing_docs, clippy::missing_errors_doc)]
337337
pub fn generate_for_test(
338338
alg: &'static Algorithm,
339339
rng: &dyn crate::rand::SecureRandom,
@@ -410,7 +410,7 @@ impl PrivateKey {
410410
let len = marshal_sec1_public_point_into_buffer(&mut public_key, evp_pkey, false)?;
411411
Ok(PublicKey {
412412
inner_key: self.inner_key.clone(),
413-
public_key,
413+
key_bytes: public_key,
414414
len,
415415
})
416416
}
@@ -419,7 +419,7 @@ impl PrivateKey {
419419
let out_len = priv_key.marshal_raw_public_to_buffer(&mut buffer)?;
420420
Ok(PublicKey {
421421
inner_key: self.inner_key.clone(),
422-
public_key: buffer,
422+
key_bytes: buffer,
423423
len: out_len,
424424
})
425425
}
@@ -522,7 +522,7 @@ const MAX_PUBLIC_KEY_LEN: usize = ec::PUBLIC_KEY_MAX_LEN;
522522
/// A public key for key agreement.
523523
pub struct PublicKey {
524524
inner_key: KeyInner,
525-
public_key: [u8; MAX_PUBLIC_KEY_LEN],
525+
key_bytes: [u8; MAX_PUBLIC_KEY_LEN],
526526
len: usize,
527527
}
528528

@@ -542,7 +542,7 @@ impl Debug for PublicKey {
542542
f.write_str(&format!(
543543
"PublicKey {{ algorithm: {:?}, bytes: \"{}\" }}",
544544
self.inner_key.algorithm(),
545-
hex::encode(&self.public_key[0..self.len])
545+
hex::encode(&self.key_bytes[0..self.len])
546546
))
547547
}
548548
}
@@ -552,15 +552,15 @@ impl AsRef<[u8]> for PublicKey {
552552
/// Octet-String-to-Elliptic-Curve-Point algorithm in
553553
/// [SEC 1: Elliptic Curve Cryptography, Version 2.0].
554554
fn as_ref(&self) -> &[u8] {
555-
&self.public_key[0..self.len]
555+
&self.key_bytes[0..self.len]
556556
}
557557
}
558558

559559
impl Clone for PublicKey {
560560
fn clone(&self) -> Self {
561561
PublicKey {
562562
inner_key: self.inner_key.clone(),
563-
public_key: self.public_key,
563+
key_bytes: self.key_bytes,
564564
len: self.len,
565565
}
566566
}
@@ -614,7 +614,7 @@ impl AsBigEndian<EcPublicKeyUncompressedBin<'static>> for PublicKey {
614614
}
615615

616616
let mut buffer = vec![0u8; self.len];
617-
buffer.copy_from_slice(&self.public_key[0..self.len]);
617+
buffer.copy_from_slice(&self.key_bytes[0..self.len]);
618618

619619
Ok(EcPublicKeyUncompressedBin::new(buffer))
620620
}

aws-lc-rs/src/agreement/ephemeral.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl EphemeralPrivateKey {
4141
}
4242

4343
#[cfg(test)]
44-
#[allow(clippy::missing_errors_doc, missing_docs)]
44+
#[allow(missing_docs, clippy::missing_errors_doc)]
4545
pub fn generate_for_test(
4646
alg: &'static Algorithm,
4747
rng: &dyn SecureRandom,

aws-lc-rs/src/bn.rs

-14
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,6 @@ impl TryFrom<&[u8]> for LcPtr<BIGNUM> {
1313
}
1414
}
1515

16-
impl TryFrom<u64> for LcPtr<BIGNUM> {
17-
type Error = ();
18-
19-
fn try_from(value: u64) -> Result<Self, Self::Error> {
20-
unsafe {
21-
let mut bn = LcPtr::new(BN_new())?;
22-
if 1 != BN_set_u64(*bn.as_mut(), value) {
23-
return Err(());
24-
}
25-
Ok(bn)
26-
}
27-
}
28-
}
29-
3016
impl TryFrom<&[u8]> for DetachableLcPtr<BIGNUM> {
3117
type Error = ();
3218

aws-lc-rs/src/digest.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ impl Context {
155155

156156
Ok(Digest {
157157
algorithm: self.algorithm,
158-
digest_msg: output,
159-
digest_len: self.algorithm.output_len,
158+
message: output,
159+
len: self.algorithm.output_len,
160160
})
161161
}
162162

@@ -199,8 +199,8 @@ pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
199199

200200
Digest {
201201
algorithm,
202-
digest_msg: output,
203-
digest_len: algorithm.output_len,
202+
message: output,
203+
len: algorithm.output_len,
204204
}
205205
}
206206

@@ -211,8 +211,8 @@ pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
211211
pub struct Digest {
212212
/// The trait `Copy` can't be implemented for dynamic arrays, so we set a
213213
/// fixed array and the appropriate length.
214-
digest_msg: [u8; MAX_OUTPUT_LEN],
215-
digest_len: usize,
214+
message: [u8; MAX_OUTPUT_LEN],
215+
len: usize,
216216

217217
algorithm: &'static Algorithm,
218218
}
@@ -229,7 +229,7 @@ impl Digest {
229229
impl AsRef<[u8]> for Digest {
230230
#[inline]
231231
fn as_ref(&self) -> &[u8] {
232-
&self.digest_msg[..self.digest_len]
232+
&self.message[..self.len]
233233
}
234234
}
235235

aws-lc-rs/src/ec.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ pub(crate) mod signature;
3131
const ELEM_MAX_BITS: usize = 521;
3232
pub(crate) const ELEM_MAX_BYTES: usize = (ELEM_MAX_BITS + 7) / 8;
3333

34-
pub(crate) const SCALAR_MAX_BYTES: usize = ELEM_MAX_BYTES;
35-
3634
/// The maximum length, in bytes, of an encoded public key.
3735
pub(crate) const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES);
3836

@@ -62,7 +60,7 @@ pub(crate) fn verify_evp_key_nid(
6260
}
6361

6462
#[inline]
65-
pub(crate) fn validate_evp_key(
63+
pub(crate) fn validate_ec_evp_key(
6664
evp_pkey: &ConstPointer<EVP_PKEY>,
6765
expected_curve_nid: i32,
6866
) -> Result<(), KeyRejected> {

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::aws_lc::{EVP_PKEY, EVP_PKEY_EC};
55
use crate::ec::encoding::sec1::parse_sec1_public_point;
6-
use crate::ec::validate_evp_key;
6+
use crate::ec::validate_ec_evp_key;
77

88
use crate::error::KeyRejected;
99
use crate::ptr::LcPtr;
@@ -23,7 +23,7 @@ pub(crate) mod sec1 {
2323
use crate::cbb::LcCBB;
2424
use crate::ec::{
2525
compressed_public_key_size_bytes, ec_group_from_nid, uncompressed_public_key_size_bytes,
26-
validate_evp_key, KeyRejected,
26+
validate_ec_evp_key, KeyRejected,
2727
};
2828
use crate::error::Unspecified;
2929
use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr};
@@ -72,7 +72,7 @@ pub(crate) mod sec1 {
7272

7373
ec_key.detach();
7474

75-
validate_evp_key(&pkey.as_const(), nid)?;
75+
validate_ec_evp_key(&pkey.as_const(), nid)?;
7676

7777
Ok(pkey)
7878
}
@@ -126,7 +126,7 @@ pub(crate) mod sec1 {
126126
ec_key.detach();
127127

128128
// Validate the EC_KEY before returning it.
129-
validate_evp_key(&pkey.as_const(), expected_curve_nid)?;
129+
validate_ec_evp_key(&pkey.as_const(), expected_curve_nid)?;
130130

131131
Ok(pkey)
132132
}
@@ -250,5 +250,5 @@ pub(crate) fn parse_ec_public_key(
250250
) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
251251
LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC)
252252
.or(parse_sec1_public_point(key_bytes, expected_curve_nid))
253-
.and_then(|key| validate_evp_key(&key.as_const(), expected_curve_nid).map(|()| key))
253+
.and_then(|key| validate_ec_evp_key(&key.as_const(), expected_curve_nid).map(|()| key))
254254
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use core::fmt::{Debug, Formatter};
1010
use crate::ec::evp_key_generate;
1111
use crate::ec::signature::{EcdsaSignatureFormat, EcdsaSigningAlgorithm, PublicKey};
1212
#[cfg(feature = "fips")]
13-
use crate::ec::validate_evp_key;
13+
use crate::ec::validate_ec_evp_key;
1414
#[cfg(not(feature = "fips"))]
1515
use crate::ec::verify_evp_key_nid;
1616

@@ -97,7 +97,7 @@ impl EcdsaKeyPair {
9797
#[cfg(not(feature = "fips"))]
9898
verify_evp_key_nid(&evp_pkey.as_const(), alg.id.nid())?;
9999
#[cfg(feature = "fips")]
100-
validate_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
100+
validate_ec_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
101101

102102
let key_pair = Self::new(alg, evp_pkey)?;
103103

@@ -188,7 +188,7 @@ impl EcdsaKeyPair {
188188
#[cfg(not(feature = "fips"))]
189189
verify_evp_key_nid(&evp_pkey.as_const(), alg.id.nid())?;
190190
#[cfg(feature = "fips")]
191-
validate_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
191+
validate_ec_evp_key(&evp_pkey.as_const(), alg.id.nid())?;
192192

193193
Ok(Self::new(alg, evp_pkey)?)
194194
}

aws-lc-rs/src/encoding.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,16 @@ macro_rules! generated_encodings {
5555
}
5656
pub(crate) use generated_encodings;
5757
generated_encodings!(
58+
(Curve25519SeedBin, Curve25519SeedBinType),
5859
(EcPrivateKeyBin, EcPrivateKeyBinType),
5960
(EcPrivateKeyRfc5915Der, EcPrivateKeyRfc5915DerType),
60-
(EcPublicKeyUncompressedBin, EcPublicKeyUncompressedBinType),
6161
(EcPublicKeyCompressedBin, EcPublicKeyCompressedBinType),
62-
(PublicKeyX509Der, PublicKeyX509DerType),
63-
(Curve25519SeedBin, Curve25519SeedBinType),
62+
(EcPublicKeyUncompressedBin, EcPublicKeyUncompressedBinType),
6463
(Pkcs8V1Der, Pkcs8V1DerType),
65-
(Pkcs8V2Der, Pkcs8V2DerType)
64+
(Pkcs8V2Der, Pkcs8V2DerType),
65+
(PqdsaPrivateKeyRaw, PqdsaPrivateKeyRawType),
66+
(PqdsaSeedRaw, PqdsaSeedRawType),
67+
(PublicKeyX509Der, PublicKeyX509DerType)
6668
);
6769

6870
/// Trait for types that can be serialized into a DER format.
@@ -82,3 +84,12 @@ pub trait AsBigEndian<T> {
8284
/// Returns Unspecified if serialization fails.
8385
fn as_be_bytes(&self) -> Result<T, crate::error::Unspecified>;
8486
}
87+
88+
/// Trait for values that can be serialized into a raw format
89+
pub trait AsRawBytes<T> {
90+
/// Serializes into a raw format.
91+
///
92+
/// # Errors
93+
/// Returns Unspecified if serialization fails.
94+
fn as_raw_bytes(&self) -> Result<T, crate::error::Unspecified>;
95+
}

aws-lc-rs/src/evp_pkey.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::aws_lc::{
1010
EVP_parse_private_key, EVP_parse_public_key, EC_KEY, EVP_PKEY, EVP_PKEY_CTX, EVP_PKEY_ED25519,
1111
RSA,
1212
};
13-
#[cfg(not(feature = "fips"))]
13+
#[cfg(all(feature = "unstable", not(feature = "fips")))]
1414
use crate::aws_lc::{
1515
EVP_PKEY_pqdsa_new_raw_private_key, EVP_PKEY_pqdsa_new_raw_public_key, EVP_PKEY_PQDSA,
1616
NID_MLDSA44, NID_MLDSA65, NID_MLDSA87,
@@ -243,7 +243,7 @@ impl LcPtr<EVP_PKEY> {
243243
bytes: &[u8],
244244
evp_pkey_type: c_int,
245245
) -> Result<Self, KeyRejected> {
246-
#[cfg(not(feature = "fips"))]
246+
#[cfg(all(feature = "unstable", not(feature = "fips")))]
247247
if evp_pkey_type == EVP_PKEY_PQDSA {
248248
return match bytes.len() {
249249
2560 => Self::new(unsafe {
@@ -257,7 +257,7 @@ impl LcPtr<EVP_PKEY> {
257257
}),
258258
_ => Err(()),
259259
}
260-
.map_err(|()| KeyRejected::unspecified());
260+
.map_err(|()| KeyRejected::invalid_encoding());
261261
}
262262

263263
Self::new(unsafe {
@@ -270,7 +270,7 @@ impl LcPtr<EVP_PKEY> {
270270
bytes: &[u8],
271271
evp_pkey_type: c_int,
272272
) -> Result<Self, KeyRejected> {
273-
#[cfg(not(feature = "fips"))]
273+
#[cfg(all(feature = "unstable", not(feature = "fips")))]
274274
if evp_pkey_type == EVP_PKEY_PQDSA {
275275
return match bytes.len() {
276276
1312 => Self::new(unsafe {

0 commit comments

Comments
 (0)