Skip to content

Commit

Permalink
EC serialization: SEC 1, RFC 5915
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Jan 28, 2025
1 parent 6906071 commit dafa981
Show file tree
Hide file tree
Showing 13 changed files with 265 additions and 289 deletions.
1 change: 0 additions & 1 deletion aws-lc-rs/src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,6 @@ impl core::fmt::Debug for Tag {
}
}

#[allow(dead_code)]
const MAX_KEY_LEN: usize = 32;

// All the AEADs we support use 128-bit tags.
Expand Down
73 changes: 29 additions & 44 deletions aws-lc-rs/src/agreement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@
//! ```
mod ephemeral;

use crate::ec::encoding::sec1::parse_sec1_private_bn;
use crate::ec::encoding;
use crate::ec::encoding::sec1::{marshal_sec1_private_key, parse_sec1_private_bn};
use crate::ec::evp_key_generate;
use crate::error::KeyRejected;
use crate::error::Unspecified;
use crate::hex;
use crate::ptr::ConstPointer;
pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey};

use crate::aws_lc::{
Expand All @@ -61,17 +67,16 @@ use crate::aws_lc::{
EVP_PKEY_new_raw_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY,
EVP_PKEY_X25519, NID_X25519,
};
use crate::ec::{encoding, evp_key_generate};
use crate::error::{KeyRejected, Unspecified};
use crate::fips::indicator_check;
use crate::ptr::{ConstPointer, LcPtr};
use crate::{ec, hex};

use crate::buffer::Buffer;
use crate::ec;
use crate::ec::encoding::rfc5915::parse_rfc5915_private_key;
use crate::encoding::{
AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der,
EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der,
};
use crate::fips::indicator_check;
use crate::ptr::LcPtr;
use core::fmt;
use core::fmt::{Debug, Formatter};
use core::ptr::null_mut;
Expand Down Expand Up @@ -107,17 +112,6 @@ impl AlgorithmID {
}
}

// Compressed public key length in bytes
#[inline]
const fn compressed_pub_key_len(&self) -> usize {
match self {
AlgorithmID::ECDH_P256 => ec::compressed_public_key_size_bytes(256),
AlgorithmID::ECDH_P384 => ec::compressed_public_key_size_bytes(384),
AlgorithmID::ECDH_P521 => ec::compressed_public_key_size_bytes(521),
AlgorithmID::X25519 => 32,
}
}

#[inline]
const fn private_key_len(&self) -> usize {
match self {
Expand Down Expand Up @@ -300,7 +294,7 @@ impl PrivateKey {
if AlgorithmID::X25519 == alg.id {
return Err(KeyRejected::invalid_encoding());
}
let evp_pkey = encoding::unmarshal_der_to_private_key(key_bytes, alg.id.nid())?;
let evp_pkey = parse_rfc5915_private_key(key_bytes, alg.id.nid())?;
Ok(Self::new(alg, evp_pkey))
}

Expand Down Expand Up @@ -416,12 +410,16 @@ impl PrivateKey {
KeyInner::ECDH_P256(evp_pkey)
| KeyInner::ECDH_P384(evp_pkey)
| KeyInner::ECDH_P521(evp_pkey) => {
let mut buffer = [0u8; MAX_PUBLIC_KEY_LEN];
let key_len = encoding::marshal_public_key_to_buffer(&mut buffer, evp_pkey, false)?;
let mut public_key = [0u8; MAX_PUBLIC_KEY_LEN];
let len = encoding::sec1::marshal_sec1_public_point_into_buffer(
&mut public_key,
evp_pkey,
false,
)?;
Ok(PublicKey {
inner_key: self.inner_key.clone(),
public_key: buffer,
len: key_len,
public_key,
len,
})
}
KeyInner::X25519(priv_key) => {
Expand Down Expand Up @@ -493,10 +491,7 @@ impl AsBigEndian<EcPrivateKeyBin<'static>> for PrivateKey {
if AlgorithmID::X25519 == self.inner_key.algorithm().id {
return Err(Unspecified);
}
let buffer = encoding::marshal_private_key_to_buffer(
self.inner_key.algorithm().id.private_key_len(),
&self.inner_key.get_evp_pkey().as_const(),
)?;
let buffer = marshal_sec1_private_key(self.inner_key.get_evp_pkey())?;
Ok(EcPrivateKeyBin::new(buffer))
}
}
Expand Down Expand Up @@ -620,17 +615,8 @@ impl AsBigEndian<EcPublicKeyCompressedBin<'static>> for PublicKey {
| KeyInner::ECDH_P521(evp_pkey) => evp_pkey,
KeyInner::X25519(_) => return Err(Unspecified),
};
let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?;

let mut buffer = vec![0u8; self.algorithm().id.compressed_pub_key_len()];

let out_len = encoding::marshal_ec_public_key_to_buffer(&mut buffer, &ec_key, true)?;

debug_assert_eq!(buffer.len(), out_len);

buffer.truncate(out_len);

Ok(EcPublicKeyCompressedBin::new(buffer))
let pub_point = encoding::sec1::marshal_sec1_public_point(evp_pkey, true)?;
Ok(EcPublicKeyCompressedBin::new(pub_point))
}
}

Expand Down Expand Up @@ -766,30 +752,29 @@ fn ec_key_ecdh<'a>(
priv_key: &LcPtr<EVP_PKEY>,
peer_pub_key_bytes: &[u8],
nid: i32,
) -> Result<&'a [u8], ()> {
let mut pub_key =
encoding::try_parse_public_key_bytes(peer_pub_key_bytes, nid).map_err(|_| ())?;
) -> Result<&'a [u8], Unspecified> {
let mut pub_key = encoding::parse_ec_public_key(peer_pub_key_bytes, nid)?;

let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?;

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

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

let mut out_key_len = buffer.len();

if 1 != indicator_check!(unsafe {
EVP_PKEY_derive(*pkey_ctx.as_mut(), buffer.as_mut_ptr(), &mut out_key_len)
}) {
return Err(());
return Err(Unspecified);
}

if 0 == out_key_len {
return Err(());
return Err(Unspecified);
}

Ok(&buffer[0..out_key_len])
Expand Down
13 changes: 0 additions & 13 deletions aws-lc-rs/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ impl<'a, T> Buffer<'a, T> {
slice.zeroize();
Buffer(Cow::Owned(owned), PhantomData)
}

// TODO: remove this "allow" once this is used.
#[allow(dead_code)]
pub(crate) fn public_from_slice(slice: &[u8]) -> Buffer<'_, T> {
Buffer(Cow::Borrowed(slice), PhantomData)
}
}

impl<T> fmt::Debug for Buffer<'_, T> {
Expand Down Expand Up @@ -75,11 +69,4 @@ mod tests {
assert_eq!(buffer.as_ref(), &[1, 2, 3]);
assert_eq!(slice, [0, 0, 0]);
}

#[test]
fn test_public_from_slice() {
let slice = [1, 2, 3];
let buffer: Buffer<u8> = Buffer::public_from_slice(&slice);
assert_eq!(buffer.as_ref(), &[1, 2, 3]);
}
}
38 changes: 36 additions & 2 deletions aws-lc-rs/src/cbb.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::{CBB_cleanup, CBB_finish, CBB_init, CBB};
use crate::aws_lc::{CBB_cleanup, CBB_finish, CBB_init, CBB_init_fixed, CBB};
use crate::error::Unspecified;
use crate::ptr::LcPtr;
use core::marker::PhantomData;
Expand All @@ -11,7 +11,6 @@ use core::ptr::null_mut;
pub(crate) struct LcCBB<'a>(CBB, PhantomData<&'a CBB>);

impl LcCBB<'static> {
#[allow(dead_code)]
pub(crate) fn new(initial_capacity: usize) -> LcCBB<'static> {
let mut cbb = MaybeUninit::<CBB>::uninit();
let cbb = unsafe {
Expand All @@ -36,6 +35,25 @@ impl LcCBB<'static> {
}
}

impl<'a> LcCBB<'a> {
pub(crate) fn new_from_slice(buffer: &'a mut [u8]) -> LcCBB<'a> {
let mut cbb = MaybeUninit::<CBB>::uninit();
let cbb = unsafe {
CBB_init_fixed(cbb.as_mut_ptr(), buffer.as_mut_ptr(), buffer.len());
cbb.assume_init()
};
Self(cbb, PhantomData)
}

pub(crate) fn finish(mut self) -> Result<usize, Unspecified> {
let mut pkcs8_bytes_ptr = null_mut::<u8>();
let mut out_len: usize = 0;
if 1 != unsafe { CBB_finish(self.as_mut_ptr(), &mut pkcs8_bytes_ptr, &mut out_len) } {
return Err(Unspecified);
}
Ok(out_len)
}
}
impl LcCBB<'_> {
pub(crate) fn as_mut_ptr(&mut self) -> *mut CBB {
&mut self.0
Expand Down Expand Up @@ -70,4 +88,20 @@ mod tests {
let vec = cbb.into_vec().expect("be copied to buffer");
assert_eq!(vec.as_slice(), &[1, 1, 255]);
}

#[test]
fn fixed_buffer() {
let mut buffer = [0u8; 4];
let mut cbb = LcCBB::new_from_slice(&mut buffer);
assert_eq!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
let out_len = cbb.finish().expect("cbb finishable");
assert_eq!(&buffer[..out_len], &[1, 1, 255]);
}

#[test]
fn fixed_buffer_no_growth() {
let mut buffer = [0u8; 1];
let mut cbb = LcCBB::new_from_slice(&mut buffer);
assert_ne!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
}
}
1 change: 0 additions & 1 deletion aws-lc-rs/src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ pub enum OperatingMode {
}

impl OperatingMode {
#[allow(dead_code)]
fn evp_cipher(&self, algorithm: &Algorithm) -> ConstPointer<EVP_CIPHER> {
ConstPointer::new(match (self, algorithm.id) {
(OperatingMode::CBC, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cbc() },
Expand Down
Loading

0 comments on commit dafa981

Please sign in to comment.