Skip to content

Commit

Permalink
WIP: to squash after review
Browse files Browse the repository at this point in the history
  • Loading branch information
Alvenix committed Mar 26, 2024
1 parent 5cf09a9 commit d52e09a
Showing 1 changed file with 115 additions and 91 deletions.
206 changes: 115 additions & 91 deletions rcgen/src/key_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt;

#[cfg(feature = "pem")]
use pem::Pem;
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
#[cfg(feature = "crypto")]
use pki_types::PrivateKeyDer;
#[cfg(feature = "crypto")]
use pki_types::PrivatePkcs8KeyDer;
Expand Down Expand Up @@ -169,11 +169,11 @@ impl KeyPair {

/// Parses the key pair from the ASCII PEM format
///
/// If the `ring` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY" in PEM files.
///
/// Otherwise if `aws_lc_rs` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS#1/RFC 3447, RFC 5915, or PKCS #8/RFC 5958;
/// If `aws_lc_rs` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS#1/RFC 3447, RFC 5915, or PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY", "RSA PRIVATE KEY", or "EC PRIVATE KEY" in PEM files.
///
/// Otherwise if the `ring` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY" in PEM files.
#[cfg(all(feature = "pem", feature = "crypto"))]
pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
let private_key = pem::parse(pem_str)._err()?;
Expand Down Expand Up @@ -328,11 +328,15 @@ impl KeyPair {
/// Obtains the key pair from a PEM formatted key
/// using the specified [`SignatureAlgorithm`]
///
/// The key must be a DER-encoded plaintext private key; as specified in PKCS#1/RFC 3447, RFC 5915, or PKCS #8/RFC 5958;
///
/// if `aws_lc_rs` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS#1/RFC 3447, RFC 5915, or PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY", "RSA PRIVATE KEY", or "EC PRIVATE KEY" in PEM files.
///
/// Otherwise if the `ring` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY" in PEM files.
///
/// Same as [from_pem_and_sign_algo](Self::from_pem_and_sign_algo).
#[cfg(all(feature = "pem", feature = "crypto", feature = "aws_lc_rs"))]
#[cfg(all(feature = "pem", feature = "crypto"))]
pub fn from_pem_and_sign_algo(
pem_str: &str,
alg: &'static SignatureAlgorithm,
Expand All @@ -348,6 +352,9 @@ impl KeyPair {
/// Obtains the key pair from a DER formatted key
/// using the specified [`SignatureAlgorithm`]
///
/// Note that using the `ring` feature, this function only support [`PrivateKeyDer::Pkcs8`] variant.
/// Consider using the `aws_lc_rs` features to support [`PrivateKeyDer`] fully.
///
/// If you have a [`PrivateKeyDer`], you can usually rely on the [`TryFrom`] implementation
/// to obtain a [`KeyPair`] -- it will determine the correct [`SignatureAlgorithm`] for you.
/// However, sometimes multiple signature algorithms fit for the same DER key. In those instances,
Expand All @@ -357,59 +364,70 @@ impl KeyPair {
/// you have already a byte slice, just calling `try_into()` will convert it to a [`PrivateKeyDer`].
///
/// [`rustls_pemfile::private_key`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.private_key.html
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
#[cfg(feature = "crypto")]
pub fn from_der_and_sign_algo(
key: &PrivateKeyDer<'_>,
alg: &'static SignatureAlgorithm,
) -> Result<Self, Error> {
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
{
if let PrivateKeyDer::Pkcs8(key) = key {
Self::from_pkcs8_der_and_sign_algo(key, alg)
} else {
Err(Error::CouldNotParseKeyPair)
}
}
#[cfg(feature = "aws_lc_rs")]
{
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));

let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};
let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};

let serialized_der = key.secret_der().to_vec();
let serialized_der = key.secret_der().to_vec();

let kind = if alg == &PKCS_ED25519 {
KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
} else if alg == &PKCS_ECDSA_P256_SHA256 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P384_SHA384 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P521_SHA512 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P521_SHA512_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_RSA_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
} else if alg == &PKCS_RSA_SHA384 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
} else if alg == &PKCS_RSA_SHA512 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
} else if alg == &PKCS_RSA_PSS_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
} else {
panic!("Unknown SignatureAlgorithm specified!");
};
let kind = if alg == &PKCS_ED25519 {
KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
} else if alg == &PKCS_ECDSA_P256_SHA256 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P384_SHA384 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P521_SHA512 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P521_SHA512_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_RSA_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
} else if alg == &PKCS_RSA_SHA384 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
} else if alg == &PKCS_RSA_SHA512 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
} else if alg == &PKCS_RSA_PSS_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
} else {
panic!("Unknown SignatureAlgorithm specified!");
};

Ok(KeyPair {
kind,
alg,
serialized_der,
})
Ok(KeyPair {
kind,
alg,
serialized_der,
})
}
}

/// Parses the key pair from the DER format
Expand All @@ -418,43 +436,54 @@ impl KeyPair {
/// you have already a byte slice, just calling `try_into()` will convert it to a [`PrivateKeyDer`].
///
/// [`rustls_pemfile::private_key`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.private_key.html
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
#[cfg(feature = "crypto")]
pub(crate) fn from_raw(
key: &PrivateKeyDer,
) -> Result<(KeyPairKind, &'static SignatureAlgorithm), Error> {
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
{
if let PrivateKeyDer::Pkcs8(key) = key {
Self::from_pkcs8_raw(key)
} else {
Err(Error::CouldNotParseKeyPair)
}
}
#[cfg(feature = "aws_lc_rs")]
{
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));

let key = key.secret_der();
let key = key.secret_der();

let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};
let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};

let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
} else if let Ok(rsakp) = rsa_key_pair_from(key) {
(
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
&PKCS_RSA_SHA256,
)
} else {
return Err(Error::CouldNotParseKeyPair);
};
Ok((kind, alg))
let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
} else if let Ok(rsakp) = rsa_key_pair_from(key) {
(
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
&PKCS_RSA_SHA256,
)
} else {
return Err(Error::CouldNotParseKeyPair);
};
Ok((kind, alg))
}
}

/// Get the raw public key of this key pair
Expand Down Expand Up @@ -597,10 +626,8 @@ impl TryFrom<&[u8]> for KeyPair {
type Error = Error;

fn try_from(key: &[u8]) -> Result<KeyPair, Error> {
#[cfg(feature = "aws_lc_rs")]
let (kind, alg) = KeyPair::from_raw(&key.try_into().map_err(|_| Error::CouldNotParseKeyPair)?)?;
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
let (kind, alg) = KeyPair::from_pkcs8_raw(&key.into())?;
let (kind, alg) =
KeyPair::from_raw(&key.try_into().map_err(|_| Error::CouldNotParseKeyPair)?)?;

Ok(KeyPair {
kind,
Expand All @@ -615,14 +642,11 @@ impl TryFrom<Vec<u8>> for KeyPair {
type Error = Error;

fn try_from(key: Vec<u8>) -> Result<KeyPair, Error> {
#[cfg(feature = "aws_lc_rs")]
let (kind, alg) = KeyPair::from_raw(
&key.as_slice()
.try_into()
.map_err(|_| Error::CouldNotParseKeyPair)?,
)?;
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
let (kind, alg) = KeyPair::from_pkcs8_raw(&key.as_slice().into())?;

Ok(KeyPair {
kind,
Expand All @@ -646,7 +670,7 @@ impl TryFrom<&PrivatePkcs8KeyDer<'_>> for KeyPair {
}
}

#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
#[cfg(feature = "crypto")]
impl TryFrom<&PrivateKeyDer<'_>> for KeyPair {
type Error = Error;

Expand Down

0 comments on commit d52e09a

Please sign in to comment.