Skip to content

Commit dcb4bfd

Browse files
committed
Consolidate agreement functions
1 parent bc79bcb commit dcb4bfd

File tree

2 files changed

+50
-88
lines changed

2 files changed

+50
-88
lines changed

aws-lc-rs/src/agreement.rs

Lines changed: 21 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ use crate::hex;
6565
pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey};
6666

6767
use crate::aws_lc::{
68-
EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY,
69-
NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_EC, EVP_PKEY_X25519,
70-
NID_X25519,
68+
i2d_ECPrivateKey, EVP_PKEY_get0_EC_KEY, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1,
69+
EVP_PKEY, EVP_PKEY_EC, EVP_PKEY_X25519, NID_X25519,
7170
};
7271

7372
use crate::buffer::Buffer;
@@ -78,7 +77,6 @@ use crate::encoding::{
7877
EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, Pkcs8V1Der, PublicKeyX509Der,
7978
};
8079
use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
81-
use crate::fips::indicator_check;
8280
use crate::pkcs8::Version;
8381
use crate::ptr::LcPtr;
8482
use core::fmt;
@@ -455,7 +453,7 @@ impl AsDer<EcPrivateKeyRfc5915Der<'static>> for PrivateKey {
455453
|evp_pkey| EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const())
456454
})?
457455
};
458-
let length = usize::try_from(unsafe { aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp) })
456+
let length = usize::try_from(unsafe { i2d_ECPrivateKey(*ec_key, &mut outp) })
459457
.map_err(|_| Unspecified)?;
460458
let mut outp = LcPtr::new(outp)?;
461459
Ok(EcPrivateKeyRfc5915Der::take_from_slice(unsafe {
@@ -712,107 +710,43 @@ where
712710

713711
let peer_pub_bytes = peer_public_key.bytes.as_ref();
714712

715-
let mut buffer = [0u8; MAX_AGREEMENT_SECRET_LEN];
716-
717-
let secret: &[u8] = match &my_private_key.inner_key {
718-
KeyInner::X25519(priv_key) => {
719-
x25519_diffie_hellman(&mut buffer, priv_key, peer_pub_bytes).or(Err(error_value))?
720-
}
721-
KeyInner::ECDH_P256(priv_key)
722-
| KeyInner::ECDH_P384(priv_key)
723-
| KeyInner::ECDH_P521(priv_key) => {
724-
ec_key_ecdh(&mut buffer, priv_key, peer_pub_bytes, expected_nid).or(Err(error_value))?
713+
let parse_result = match &my_private_key.inner_key {
714+
KeyInner::X25519(_) => try_parse_x25519_public_key_bytes(peer_pub_bytes),
715+
KeyInner::ECDH_P256(_) | KeyInner::ECDH_P384(_) | KeyInner::ECDH_P521(_) => {
716+
encoding::parse_ec_public_key(peer_pub_bytes, expected_nid)
725717
}
726718
};
727-
kdf(secret)
728-
}
729-
730-
// Current max secret length is P-521's.
731-
const MAX_AGREEMENT_SECRET_LEN: usize = AlgorithmID::ECDH_P521.private_key_len();
732-
733-
#[inline]
734-
#[allow(clippy::needless_pass_by_value)]
735-
fn ec_key_ecdh<'a>(
736-
buffer: &'a mut [u8; MAX_AGREEMENT_SECRET_LEN],
737-
priv_key: &LcPtr<EVP_PKEY>,
738-
peer_pub_key_bytes: &[u8],
739-
nid: i32,
740-
) -> Result<&'a [u8], Unspecified> {
741-
let mut pub_key = encoding::parse_ec_public_key(peer_pub_key_bytes, nid)?;
742-
743-
let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?;
744-
745-
if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx.as_mut()) } {
746-
return Err(Unspecified);
747-
}
748-
749-
if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } {
750-
return Err(Unspecified);
751-
}
752-
753-
let mut out_key_len = buffer.len();
754-
755-
if 1 != indicator_check!(unsafe {
756-
EVP_PKEY_derive(*pkey_ctx.as_mut(), buffer.as_mut_ptr(), &mut out_key_len)
757-
}) {
758-
return Err(Unspecified);
759-
}
760719

761-
if 0 == out_key_len {
762-
return Err(Unspecified);
763-
}
764-
765-
Ok(&buffer[0..out_key_len])
766-
}
767-
768-
#[inline]
769-
fn x25519_diffie_hellman<'a>(
770-
buffer: &'a mut [u8; MAX_AGREEMENT_SECRET_LEN],
771-
priv_key: &LcPtr<EVP_PKEY>,
772-
peer_pub_key: &[u8],
773-
) -> Result<&'a [u8], ()> {
774-
let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?;
775-
776-
if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx.as_mut()) } {
777-
return Err(());
778-
}
720+
if let Ok(peer_pub_key) = parse_result {
721+
let secret = my_private_key
722+
.inner_key
723+
.get_evp_pkey()
724+
.agree(&peer_pub_key)
725+
.or(Err(error_value))?;
779726

780-
let mut pub_key = try_parse_x25519_public_key_bytes(peer_pub_key)?;
781-
782-
if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } {
783-
return Err(());
784-
}
785-
786-
let mut out_key_len = buffer.len();
787-
788-
if 1 != indicator_check!(unsafe {
789-
EVP_PKEY_derive(*pkey_ctx.as_mut(), buffer.as_mut_ptr(), &mut out_key_len)
790-
}) {
791-
return Err(());
727+
kdf(secret.as_ref())
728+
} else {
729+
Err(error_value)
792730
}
793-
794-
debug_assert!(out_key_len == AlgorithmID::X25519.pub_key_len());
795-
796-
Ok(&buffer[0..AlgorithmID::X25519.pub_key_len()])
797731
}
798732

799733
pub(crate) fn try_parse_x25519_public_key_bytes(
800734
key_bytes: &[u8],
801-
) -> Result<LcPtr<EVP_PKEY>, Unspecified> {
735+
) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
802736
LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_X25519)
803737
.or(try_parse_x25519_public_key_raw_bytes(key_bytes))
804738
}
805739

806-
fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_PKEY>, Unspecified> {
740+
fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
807741
let expected_pub_key_len = X25519.id.pub_key_len();
808742
if key_bytes.len() != expected_pub_key_len {
809-
return Err(Unspecified);
743+
return Err(KeyRejected::invalid_encoding());
810744
}
811745

812-
Ok(LcPtr::<EVP_PKEY>::parse_raw_public_key(
746+
LcPtr::<EVP_PKEY>::parse_raw_public_key(
813747
key_bytes,
814748
EVP_PKEY_X25519,
815-
)?)
749+
)
816750
}
817751

818752
#[cfg(test)]

aws-lc-rs/src/evp_pkey.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
use crate::aws_lc::{
55
EVP_DigestSign, EVP_DigestSignInit, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_CTX_new,
6-
EVP_PKEY_CTX_new_id, EVP_PKEY_bits, EVP_PKEY_cmp, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA,
6+
EVP_PKEY_CTX_new_id, EVP_PKEY_bits, EVP_PKEY_cmp, EVP_PKEY_derive, EVP_PKEY_derive_init,
7+
EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA,
78
EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key, EVP_PKEY_id, EVP_PKEY_keygen,
89
EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_PKEY_sign,
910
EVP_PKEY_sign_init, EVP_PKEY_size, EVP_PKEY_up_ref, EVP_PKEY_verify, EVP_PKEY_verify_init,
@@ -491,6 +492,33 @@ impl LcPtr<EVP_PKEY> {
491492
}
492493
}
493494

495+
pub(crate) fn agree(&self, peer_key: &Self) -> Result<Box<[u8]>, Unspecified> {
496+
let mut pctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.as_mut_unsafe(), null_mut()) })?;
497+
498+
if 1 != unsafe { EVP_PKEY_derive_init(*pctx.as_mut()) } {
499+
return Err(Unspecified);
500+
}
501+
502+
let mut secret_len = 0;
503+
if 1 != unsafe { EVP_PKEY_derive_set_peer(*pctx.as_mut(), *peer_key.as_mut_unsafe()) } {
504+
return Err(Unspecified);
505+
}
506+
507+
if 1 != unsafe { EVP_PKEY_derive(*pctx.as_mut(), null_mut(), &mut secret_len) } {
508+
return Err(Unspecified);
509+
}
510+
511+
let mut secret = vec![0u8; secret_len];
512+
if 1 != indicator_check!(unsafe {
513+
EVP_PKEY_derive(*pctx.as_mut(), secret.as_mut_ptr(), &mut secret_len)
514+
}) {
515+
return Err(Unspecified);
516+
}
517+
secret.truncate(secret_len);
518+
519+
Ok(secret.into_boxed_slice())
520+
}
521+
494522
pub(crate) fn generate<F>(pkey_type: c_int, params_fn: Option<F>) -> Result<Self, Unspecified>
495523
where
496524
F: EVP_PKEY_CTX_consumer,

0 commit comments

Comments
 (0)