Skip to content

Commit

Permalink
RSA Key Generation Support
Browse files Browse the repository at this point in the history
  • Loading branch information
skmcgrail committed Jan 19, 2024
1 parent 32f6aa6 commit cb55b4d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 7 deletions.
2 changes: 2 additions & 0 deletions aws-lc-rs/src/cbb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::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 @@ -21,6 +22,7 @@ impl LcCBB<'static> {
Self(cbb, PhantomData)
}

#[allow(dead_code)]
pub(crate) fn into_buffer<'a, T>(mut self) -> Result<Buffer<'a, T>, Unspecified> {
let mut out_data = null_mut::<u8>();
let mut out_len: usize = 0;
Expand Down
9 changes: 9 additions & 0 deletions aws-lc-rs/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::encoding::types::{
EcPublicKeyX509DerType,
};

use self::types::Pkcs8V1DerType;

mod types {
pub struct EcPrivateKeyBinType {
_priv: (),
Expand All @@ -25,6 +27,10 @@ mod types {
pub struct Curve25519SeedBufferType {
_priv: (),
}

pub struct Pkcs8V1DerType {
_priv: (),
}
}

/// Trait for types that can be serialized into a DER format.
Expand Down Expand Up @@ -56,3 +62,6 @@ pub type EcPublicKeyX509Der<'a> = Buffer<'a, EcPublicKeyX509DerType>;

/// Elliptic curve private key data encoded as a big-endian fixed-length integer.
pub type Curve25519SeedBin<'a> = Buffer<'a, Curve25519SeedBufferType>;

/// A PKCS#8 v1 (RFC 5208) DER encoded structure.
pub type Pkcs8V1Der<'a> = Buffer<'a, Pkcs8V1DerType>;
90 changes: 83 additions & 7 deletions aws-lc-rs/src/rsa/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ use core::{
ptr::null_mut,
};

use crate::fips::indicator_check;
use crate::{
buffer::Buffer,
encoding::{AsDer, Pkcs8V1Der},
fips::indicator_check,
};

#[cfg(feature = "fips")]
use aws_lc::RSA_check_fips;
Expand All @@ -29,6 +33,7 @@ use untrusted::Input;
use zeroize::Zeroize;

use super::{
encoding,
signature::{compute_rsa_signature, RsaEncoding, RsaPadding},
RsaParameters,
};
Expand All @@ -44,10 +49,6 @@ use crate::{
sealed::Sealed,
};

// Based on a meassurement of a PKCS#8 v1 document containing an RSA-8192 key with an additional 1% capacity buffer
// rounded to an even 64-bit words (4678 + 1% + padding ≈ 4728).
pub(super) const PKCS8_FIXED_CAPACITY_BUFFER: usize = 4728;

/// RSA key-size.
#[allow(clippy::module_name_repetitions)]
#[non_exhaustive]
Expand Down Expand Up @@ -139,12 +140,14 @@ impl KeyPair {
/// # Errors
/// * `Unspecified`: Any key generation failure.
#[cfg(feature = "fips")]
pub fn generate_fips(size: SignatureKeySize) -> Result<Self, Unspecified> {
pub fn generate_fips(size: KeySize) -> Result<Self, Unspecified> {
let private_key = generate_rsa_key(size.bit_len(), true)?;
Self::new(private_key).map_err(|_| Unspecified)
}

/// Parses an unencrypted PKCS#8-encoded RSA private key.
///
/// A RSA keypair may be generated using [`KeyPair::generate`].
///
/// Only two-prime (not multi-prime) keys are supported. The public modulus
/// (n) must be at least 2047 bits. The public modulus must be no larger
Expand Down Expand Up @@ -193,7 +196,7 @@ impl KeyPair {
/// not acceptable.
pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
unsafe {
let evp_pkey = LcPtr::try_from(pkcs8)?;
let evp_pkey = encoding::pkcs8::decode_der(pkcs8)?;
Self::validate_rsa_pkey(&evp_pkey)?;
Self::new(evp_pkey)
}
Expand Down Expand Up @@ -357,6 +360,12 @@ impl crate::signature::KeyPair for KeyPair {
}
}

impl AsDer<Pkcs8V1Der<'static>> for KeyPair {
fn as_der(&self) -> Result<Pkcs8V1Der<'static>, Unspecified> {
Ok(Buffer::new(encoding::pkcs8::encode_v1_der(&self.evp_pkey)?))
}
}

#[inline]
#[allow(non_snake_case)]
unsafe fn build_private_RSA_PKEY(private_key: &[u8]) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
Expand Down Expand Up @@ -605,3 +614,70 @@ pub(super) fn generate_rsa_key(

Ok(evp_pkey)
}

#[cfg(test)]
mod tests {
use super::{KeyPair, KeySize, PublicKeyComponents};
use crate::encoding::AsDer;

macro_rules! generate_encode_decode {
($name:ident, $size:expr) => {
#[test]
fn $name() {
let private_key = KeyPair::generate($size).expect("generation");

let pkcs8v1 = private_key.as_der().expect("encoded");

let private_key = KeyPair::from_pkcs8(pkcs8v1.as_ref()).expect("decoded");

let public_key = crate::signature::KeyPair::public_key(&private_key);

let _ = public_key.as_ref();
}
};
}

generate_encode_decode!(rsa2048_generate_encode_decode, KeySize::Rsa2048);
generate_encode_decode!(rsa3072_generate_encode_decode, KeySize::Rsa3072);
generate_encode_decode!(rsa4096_generate_encode_decode, KeySize::Rsa4096);
generate_encode_decode!(rsa8192_generate_encode_decode, KeySize::Rsa8192);

macro_rules! generate_fips_encode_decode {
($name:ident, $size:expr) => {
#[cfg(feature = "fips")]
#[test]
fn $name() {
let private_key = KeyPair::generate_fips($size).expect("generation");

let pkcs8v1 = private_key.as_der().expect("encoded");

let private_key = KeyPair::from_pkcs8(pkcs8v1.as_ref()).expect("decoded");

let public_key = crate::signature::KeyPair::public_key(&private_key);

let _ = public_key.as_ref();
}
};
($name:ident, $size:expr, false) => {
#[cfg(feature = "fips")]
#[test]
fn $name() {
let _ = KeyPair::generate_fips($size).expect_err("should fail for key size");
}
};
}

generate_fips_encode_decode!(rsa2048_generate_fips_encode_decode, KeySize::Rsa2048);
generate_fips_encode_decode!(rsa3072_generate_fips_encode_decode, KeySize::Rsa3072);
generate_fips_encode_decode!(rsa4096_generate_fips_encode_decode, KeySize::Rsa4096);
generate_fips_encode_decode!(rsa8192_generate_fips_encode_decode, KeySize::Rsa8192, false);

#[test]
fn public_key_components_clone_debug() {
let pkc = PublicKeyComponents::<&[u8]> {
n: &[0x63, 0x61, 0x6d, 0x65, 0x6c, 0x6f, 0x74],
e: &[0x61, 0x76, 0x61, 0x6c, 0x6f, 0x6e],
};
assert_eq!("RsaPublicKeyComponents { n: [99, 97, 109, 101, 108, 111, 116], e: [97, 118, 97, 108, 111, 110] }", format!("{pkc:?}"));
}
}

0 comments on commit cb55b4d

Please sign in to comment.