Skip to content

Commit

Permalink
add aws_lc_rs support to use as crypto backend
Browse files Browse the repository at this point in the history
  • Loading branch information
BiagioFesta committed Dec 13, 2023
1 parent 53a5232 commit b2860b2
Show file tree
Hide file tree
Showing 10 changed files with 518 additions and 128 deletions.
505 changes: 413 additions & 92 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions rcgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ name = "sign-leaf-with-ca"
required-features = ["pem", "x509-parser"]

[dependencies]
aws-lc-rs = { version = "1.0.0", optional = true }
yasna = { version = "0.5.2", features = ["time", "std"] }
ring = "0.17"
ring = { version = "0.17", optional = true }
pem = { workspace = true, optional = true }
time = { version = "0.3.6", default-features = false }
x509-parser = { version = "0.15", features = ["verify"], optional = true }
zeroize = { version = "1.2", optional = true }

[features]
default = ["pem"]
default = ["pem", "ring"]
aws_lc_rs = ["dep:aws-lc-rs"]
ring = ["dep:ring"]

[package.metadata.docs.rs]
features = ["x509-parser"]
Expand Down
2 changes: 1 addition & 1 deletion rcgen/examples/rsa-irc-openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let pem_serialized = cert.serialize_pem()?;
let pem = pem::parse(&pem_serialized)?;
let der_serialized = pem.contents();
let hash = ring::digest::digest(&ring::digest::SHA512, der_serialized);
let hash = rcgen::ring_like::digest::digest(&rcgen::ring_like::digest::SHA512, der_serialized);
let hash_hex = hash.as_ref().iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{b:02x}");
output
Expand Down
2 changes: 1 addition & 1 deletion rcgen/examples/rsa-irc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let pem_serialized = cert.serialize_pem()?;
let pem = pem::parse(&pem_serialized)?;
let der_serialized = pem.contents();
let hash = ring::digest::digest(&ring::digest::SHA512, der_serialized);
let hash = rcgen::ring_like::digest::digest(&rcgen::ring_like::digest::SHA512, der_serialized);
let hash_hex = hash.as_ref().iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{b:02x}");
output
Expand Down
43 changes: 23 additions & 20 deletions rcgen/src/key_pair.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#[cfg(feature = "pem")]
use pem::Pem;
use ring::rand::SystemRandom;
use ring::signature::KeyPair as RingKeyPair;
use ring::signature::{self, EcdsaKeyPair, Ed25519KeyPair, RsaEncoding, RsaKeyPair};
use std::convert::TryFrom;
use std::fmt;
use yasna::DERWriter;

use crate::error::ExternalError;
use crate::ring_like::error as ring_error;
use crate::ring_like::rand::SystemRandom;
use crate::ring_like::signature::KeyPair as RingKeyPair;
use crate::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, RsaEncoding, RsaKeyPair};
use crate::ring_like::{ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len};
use crate::sign_algo::algo::*;
use crate::sign_algo::SignAlgo;
#[cfg(feature = "pem")]
Expand Down Expand Up @@ -115,15 +117,17 @@ impl KeyPair {
let kind = if alg == &PKCS_ED25519 {
KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8)._err()?)
} else if alg == &PKCS_ECDSA_P256_SHA256 {
KeyPairKind::Ec(
EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, rng)
._err()?,
)
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
pkcs8,
rng,
)?)
} else if alg == &PKCS_ECDSA_P384_SHA384 {
KeyPairKind::Ec(
EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, rng)
._err()?,
)
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
pkcs8,
rng,
)?)
} else if alg == &PKCS_RSA_SHA256 {
let rsakp = RsaKeyPair::from_pkcs8(pkcs8)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
Expand Down Expand Up @@ -154,11 +158,11 @@ impl KeyPair {
let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) =
EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
ecdsa_from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) =
EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
ecdsa_from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
Expand All @@ -181,8 +185,7 @@ impl KeyPair {
let key_pair_doc = EcdsaKeyPair::generate_pkcs8(sign_alg, rng)._err()?;
let key_pair_serialized = key_pair_doc.as_ref().to_vec();

let key_pair =
EcdsaKeyPair::from_pkcs8(&sign_alg, &&key_pair_doc.as_ref(), rng).unwrap();
let key_pair = ecdsa_from_pkcs8(&sign_alg, &&key_pair_doc.as_ref(), rng).unwrap();
Ok(KeyPair {
kind: KeyPairKind::Ec(key_pair),
alg,
Expand Down Expand Up @@ -242,7 +245,7 @@ impl KeyPair {
},
KeyPairKind::Rsa(kp, padding_alg) => {
let system_random = SystemRandom::new();
let mut signature = vec![0; kp.public().modulus_len()];
let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
kp.sign(*padding_alg, &system_random, msg, &mut signature)
._err()?;
let sig = &signature.as_ref();
Expand Down Expand Up @@ -371,13 +374,13 @@ pub trait RemoteKeyPair {
fn algorithm(&self) -> &'static SignatureAlgorithm;
}

impl<T> ExternalError<T> for Result<T, ring::error::KeyRejected> {
impl<T> ExternalError<T> for Result<T, ring_error::KeyRejected> {
fn _err(self) -> Result<T, Error> {
self.map_err(|e| Error::RingKeyRejected(e.to_string()))
}
}

impl<T> ExternalError<T> for Result<T, ring::error::Unspecified> {
impl<T> ExternalError<T> for Result<T, ring_error::Unspecified> {
fn _err(self) -> Result<T, Error> {
self.map_err(|_| Error::RingUnspecified)
}
Expand Down Expand Up @@ -407,8 +410,8 @@ pub(crate) trait PublicKeyData {
mod test {
use super::*;

use ring::rand::SystemRandom;
use ring::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
use crate::ring_like::rand::SystemRandom;
use crate::ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};

#[test]
fn test_algorithm() {
Expand Down
4 changes: 3 additions & 1 deletion rcgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ println!("{}", cert.serialize_private_key_pem());

#[cfg(feature = "pem")]
use pem::Pem;
use ring::digest;
use ring_like::digest;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt;
Expand Down Expand Up @@ -116,6 +116,8 @@ mod csr;
mod error;
mod key_pair;
mod oid;
/// re-export of crypto functions (back-ed by `ring` or `aws-lc-rs`)
pub mod ring_like;
mod sign_algo;

// Example certs usable as reference:
Expand Down
55 changes: 55 additions & 0 deletions rcgen/src/ring_like.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#[cfg(feature = "ring")]
pub use ring::*;

#[cfg(feature = "aws_lc_rs")]
pub use aws_lc_rs::*;

use crate::{error::ExternalError, Error};

/// Constructs an ECDSA key pair by parsing an unencrypted PKCS#8 v1
/// id-ecPublicKey `ECPrivateKey` key.
///
/// The input must be in PKCS#8 v1 format. It must contain the public key in
/// the `ECPrivateKey` structure; `from_pkcs8()` will verify that the public
/// key and the private key are consistent with each other. The algorithm
/// identifier must identify the curve by name; it must not use an
/// "explicit" encoding of the curve. The `parameters` field of the
/// `ECPrivateKey`, if present, must be the same named curve that is in the
/// algorithm identifier in the PKCS#8 header.
pub fn ecdsa_from_pkcs8(
alg: &'static signature::EcdsaSigningAlgorithm,
pkcs8: &[u8],
_rng: &dyn rand::SecureRandom,
) -> Result<signature::EcdsaKeyPair, Error> {
#[cfg(feature = "ring")]
{
Ok(signature::EcdsaKeyPair::from_pkcs8(alg, pkcs8, _rng)._err()?)
}

#[cfg(feature = "aws_lc_rs")]
{
Ok(signature::EcdsaKeyPair::from_pkcs8(alg, pkcs8)._err()?)
}
}

/// The length, in bytes, of the public modulus.
///
/// The modulus length is rounded up to a whole number of bytes if its
/// bit length isn't a multiple of 8.
pub fn rsa_key_pair_public_modulus_len(kp: &signature::RsaKeyPair) -> usize {
#[cfg(feature = "ring")]
{
kp.public().modulus_len()
}

#[cfg(feature = "aws_lc_rs")]
{
kp.public_modulus_len()
}
}

#[cfg(all(feature = "ring", feature = "aws_lc_rs"))]
compile_error!("Only one feature among 'ring' and 'aws_lc_rs' can be active at the same time");

#[cfg(not(any(feature = "ring", feature = "aws_lc_rs")))]
compile_error!("At least one of the features among 'ring' and 'aws_lc_rs' must be activated");
2 changes: 1 addition & 1 deletion rcgen/src/sign_algo.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use ring::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters};
use std::fmt;
use std::hash::{Hash, Hasher};
use yasna::models::ObjectIdentifier;
use yasna::DERWriter;
use yasna::Tag;

use crate::oid::*;
use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters};
use crate::Error;

pub(crate) enum SignAlgo {
Expand Down
24 changes: 15 additions & 9 deletions rcgen/tests/webpki.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ use webpki::{
};
use webpki::{DnsNameRef, Time};

use ring::rand::SystemRandom;
use ring::signature::{self, EcdsaKeyPair, EcdsaSigningAlgorithm, Ed25519KeyPair, KeyPair as _};
use rcgen::ring_like::rand::SystemRandom;
use rcgen::ring_like::signature::{
self, EcdsaKeyPair, EcdsaSigningAlgorithm, Ed25519KeyPair, KeyPair as _,
};
#[cfg(feature = "pem")]
use ring::signature::{RsaEncoding, RsaKeyPair};
use rcgen::ring_like::signature::{RsaEncoding, RsaKeyPair};

use std::convert::TryFrom;
use time::{Duration, OffsetDateTime};
Expand All @@ -25,8 +27,12 @@ mod util;

fn sign_msg_ecdsa(cert: &Certificate, msg: &[u8], alg: &'static EcdsaSigningAlgorithm) -> Vec<u8> {
let pk_der = cert.serialize_private_key_der();
let key_pair =
EcdsaKeyPair::from_pkcs8(alg, &pk_der, &ring::rand::SystemRandom::new()).unwrap();
let key_pair = rcgen::ring_like::ecdsa_from_pkcs8(
alg,
&pk_der,
&rcgen::ring_like::rand::SystemRandom::new(),
)
.unwrap();
let system_random = SystemRandom::new();
let signature = key_pair.sign(&system_random, msg).unwrap();
signature.as_ref().to_vec()
Expand All @@ -44,7 +50,7 @@ fn sign_msg_rsa(cert: &Certificate, msg: &[u8], encoding: &'static dyn RsaEncodi
let pk_der = cert.serialize_private_key_der();
let key_pair = RsaKeyPair::from_pkcs8(&pk_der).unwrap();
let system_random = SystemRandom::new();
let mut signature = vec![0; key_pair.public().modulus_len()];
let mut signature = vec![0; rcgen::ring_like::rsa_key_pair_public_modulus_len(&key_pair)];
key_pair
.sign(encoding, &system_random, msg, &mut signature)
.unwrap();
Expand Down Expand Up @@ -335,15 +341,15 @@ fn from_remote() {
}
}

let rng = ring::rand::SystemRandom::new();
let rng = rcgen::ring_like::rand::SystemRandom::new();
let key_pair = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256).unwrap();
let remote = EcdsaKeyPair::from_pkcs8(
let remote = rcgen::ring_like::ecdsa_from_pkcs8(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&key_pair.serialize_der(),
&rng,
)
.unwrap();
let key_pair = EcdsaKeyPair::from_pkcs8(
let key_pair = rcgen::ring_like::ecdsa_from_pkcs8(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&key_pair.serialize_der(),
&rng,
Expand Down
2 changes: 1 addition & 1 deletion rustls-cert-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ edition.workspace = true
keywords.workspace = true

[dependencies]
rcgen = { path = "../rcgen" }
rcgen = { path = "../rcgen", default-features = false }
pem = { workspace = true }

0 comments on commit b2860b2

Please sign in to comment.