Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/rust/cryptography-key-parsing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ impl From<openssl::error::ErrorStack> for KeyParsingError {
}

pub type KeyParsingResult<T> = Result<T, KeyParsingError>;
pub type PrivateKeyParser = fn(&[u8]) -> KeyParsingResult<ParsedPrivateKey>;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't make much sense to export this type alias here, it's just a random function signature.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to keys.rs as an inline type (but that's required as a separate type because clippy complains otherwise).


pub enum ParsedPrivateKey {
Pkey(openssl::pkey::PKey<openssl::pkey::Private>),
}

pub enum ParsedPublicKey {
Pkey(openssl::pkey::PKey<openssl::pkey::Public>),
}

pub enum KeySerializationError {
PasswordMustBeUtf8,
Expand Down
48 changes: 26 additions & 22 deletions src/rust/cryptography-key-parsing/src/pkcs8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cryptography_x509::pkcs8::EncryptedPrivateKeyInfo;

#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
use crate::MIN_DH_MODULUS_SIZE;
use crate::{ec, pbe, rsa, KeyParsingError, KeyParsingResult};
use crate::{ec, pbe, rsa, KeyParsingError, KeyParsingResult, ParsedPrivateKey};

// RFC 5208 Section 5
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
Expand Down Expand Up @@ -44,19 +44,17 @@ pub fn mldsa_seed_from_pkey(
Ok(asn1::parse_single::<MlDsaPrivateKey>(pki.private_key).unwrap())
}

pub fn parse_private_key(
data: &[u8],
) -> KeyParsingResult<openssl::pkey::PKey<openssl::pkey::Private>> {
pub fn parse_private_key(data: &[u8]) -> KeyParsingResult<ParsedPrivateKey> {
let k = asn1::parse_single::<PrivateKeyInfo<'_>>(data)?;
if k.version != 0 {
return Err(crate::KeyParsingError::InvalidKey);
}
match k.algorithm.params {
AlgorithmParameters::Rsa(_) | AlgorithmParameters::RsaPss(_) => {
rsa::parse_pkcs1_private_key(k.private_key)
rsa::parse_pkcs1_private_key(k.private_key).map(ParsedPrivateKey::Pkey)
}
AlgorithmParameters::Ec(ec_params) => {
ec::parse_pkcs1_private_key(k.private_key, Some(ec_params))
ec::parse_pkcs1_private_key(k.private_key, Some(ec_params)).map(ParsedPrivateKey::Pkey)
}

AlgorithmParameters::Dsa(dsa_params) => {
Expand All @@ -73,30 +71,31 @@ pub fn parse_private_key(

let dsa =
openssl::dsa::Dsa::from_private_components(p, q, g, dsa_private_key, pub_key)?;
Ok(openssl::pkey::PKey::from_dsa(dsa)?)
Ok(ParsedPrivateKey::Pkey(openssl::pkey::PKey::from_dsa(dsa)?))
}

#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
AlgorithmParameters::Dh(dh_params) => {
let p = openssl::bn::BigNum::from_slice(dh_params.p.as_bytes())?;
let g = openssl::bn::BigNum::from_slice(dh_params.g.as_bytes())?;
let q = Some(openssl::bn::BigNum::from_slice(dh_params.q.as_bytes())?);
parse_dh_private_key(k.private_key, p, g, q)
parse_dh_private_key(k.private_key, p, g, q).map(ParsedPrivateKey::Pkey)
}

#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
AlgorithmParameters::DhKeyAgreement(dh_params) => {
let p = openssl::bn::BigNum::from_slice(dh_params.p.as_bytes())?;
let g = openssl::bn::BigNum::from_slice(dh_params.g.as_bytes())?;
parse_dh_private_key(k.private_key, p, g, None)
parse_dh_private_key(k.private_key, p, g, None).map(ParsedPrivateKey::Pkey)
}

AlgorithmParameters::X25519 => {
let key_bytes = asn1::parse_single(k.private_key)?;
Ok(openssl::pkey::PKey::private_key_from_raw_bytes(
let pkey = openssl::pkey::PKey::private_key_from_raw_bytes(
key_bytes,
openssl::pkey::Id::X25519,
)?)
)?;
Ok(ParsedPrivateKey::Pkey(pkey))
}
#[cfg(not(any(
CRYPTOGRAPHY_IS_LIBRESSL,
Expand All @@ -105,17 +104,19 @@ pub fn parse_private_key(
)))]
AlgorithmParameters::X448 => {
let key_bytes = asn1::parse_single(k.private_key)?;
Ok(openssl::pkey::PKey::private_key_from_raw_bytes(
let pkey = openssl::pkey::PKey::private_key_from_raw_bytes(
key_bytes,
openssl::pkey::Id::X448,
)?)
)?;
Ok(ParsedPrivateKey::Pkey(pkey))
}
AlgorithmParameters::Ed25519 => {
let key_bytes = asn1::parse_single(k.private_key)?;
Ok(openssl::pkey::PKey::private_key_from_raw_bytes(
let pkey = openssl::pkey::PKey::private_key_from_raw_bytes(
key_bytes,
openssl::pkey::Id::ED25519,
)?)
)?;
Ok(ParsedPrivateKey::Pkey(pkey))
}
#[cfg(not(any(
CRYPTOGRAPHY_IS_LIBRESSL,
Expand All @@ -124,19 +125,22 @@ pub fn parse_private_key(
)))]
AlgorithmParameters::Ed448 => {
let key_bytes = asn1::parse_single(k.private_key)?;
Ok(openssl::pkey::PKey::private_key_from_raw_bytes(
let pkey = openssl::pkey::PKey::private_key_from_raw_bytes(
key_bytes,
openssl::pkey::Id::ED448,
)?)
)?;
Ok(ParsedPrivateKey::Pkey(pkey))
}

#[cfg(CRYPTOGRAPHY_IS_AWSLC)]
AlgorithmParameters::MlDsa65 => {
let MlDsaPrivateKey::Seed(seed) = asn1::parse_single::<MlDsaPrivateKey>(k.private_key)?;
Ok(cryptography_openssl::mldsa::new_raw_private_key(
cryptography_openssl::mldsa::MlDsaVariant::MlDsa65,
&seed,
)?)
Ok(ParsedPrivateKey::Pkey(
cryptography_openssl::mldsa::new_raw_private_key(
cryptography_openssl::mldsa::MlDsaVariant::MlDsa65,
&seed,
)?,
))
}

_ => Err(KeyParsingError::UnsupportedKeyType(
Expand Down Expand Up @@ -223,7 +227,7 @@ fn pkcs5_pbe_decrypt(
pub fn parse_encrypted_private_key(
data: &[u8],
password: Option<&[u8]>,
) -> KeyParsingResult<openssl::pkey::PKey<openssl::pkey::Private>> {
) -> KeyParsingResult<ParsedPrivateKey> {
let epki = asn1::parse_single::<EncryptedPrivateKeyInfo<'_>>(data)?;
let password = match password {
None | Some(b"") => return Err(KeyParsingError::EncryptedKeyWithoutPassword),
Expand Down
76 changes: 43 additions & 33 deletions src/rust/cryptography-key-parsing/src/spki.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ use cryptography_x509::common::{
SubjectPublicKeyInfo,
};

use crate::{KeyParsingError, KeyParsingResult, KeySerializationResult};
use crate::{KeyParsingError, KeyParsingResult, KeySerializationResult, ParsedPublicKey};

pub fn parse_public_key(
data: &[u8],
) -> KeyParsingResult<openssl::pkey::PKey<openssl::pkey::Public>> {
pub fn parse_public_key(data: &[u8]) -> KeyParsingResult<ParsedPublicKey> {
let k = asn1::parse_single::<SubjectPublicKeyInfo<'_>>(data)?;

match k.algorithm.params {
Expand All @@ -25,41 +23,51 @@ pub fn parse_public_key(
)
.map_err(|_| KeyParsingError::InvalidKey)?;
let ec_key = openssl::ec::EcKey::from_public_key(&group, &ec_point)?;
Ok(openssl::pkey::PKey::from_ec_key(ec_key)?)
let pkey = openssl::pkey::PKey::from_ec_key(ec_key)?;
Ok(ParsedPublicKey::Pkey(pkey))
}
AlgorithmParameters::Ed25519 => Ok(openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::ED25519,
)
.map_err(|_| KeyParsingError::InvalidKey)?),
AlgorithmParameters::Ed25519 => Ok(ParsedPublicKey::Pkey(
openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::ED25519,
)
.map_err(|_| KeyParsingError::InvalidKey)?,
)),
#[cfg(not(any(
CRYPTOGRAPHY_IS_LIBRESSL,
CRYPTOGRAPHY_IS_BORINGSSL,
CRYPTOGRAPHY_IS_AWSLC
)))]
AlgorithmParameters::Ed448 => Ok(openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::ED448,
)
.map_err(|_| KeyParsingError::InvalidKey)?),
AlgorithmParameters::X25519 => Ok(openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::X25519,
)
.map_err(|_| KeyParsingError::InvalidKey)?),
AlgorithmParameters::Ed448 => Ok(ParsedPublicKey::Pkey(
openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::ED448,
)
.map_err(|_| KeyParsingError::InvalidKey)?,
)),
AlgorithmParameters::X25519 => Ok(ParsedPublicKey::Pkey(
openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::X25519,
)
.map_err(|_| KeyParsingError::InvalidKey)?,
)),
#[cfg(not(any(
CRYPTOGRAPHY_IS_LIBRESSL,
CRYPTOGRAPHY_IS_BORINGSSL,
CRYPTOGRAPHY_IS_AWSLC
)))]
AlgorithmParameters::X448 => Ok(openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::X448,
)
.map_err(|_| KeyParsingError::InvalidKey)?),
AlgorithmParameters::X448 => Ok(ParsedPublicKey::Pkey(
openssl::pkey::PKey::public_key_from_raw_bytes(
k.subject_public_key.as_bytes(),
openssl::pkey::Id::X448,
)
.map_err(|_| KeyParsingError::InvalidKey)?,
)),
AlgorithmParameters::Rsa(_) | AlgorithmParameters::RsaPss(_) => {
// RSA-PSS keys are treated the same as bare RSA keys.
crate::rsa::parse_pkcs1_public_key(k.subject_public_key.as_bytes())
.map(ParsedPublicKey::Pkey)
}
AlgorithmParameters::Dsa(dsa_params) => {
let p = openssl::bn::BigNum::from_slice(dsa_params.p.as_bytes())?;
Expand All @@ -71,7 +79,7 @@ pub fn parse_public_key(
let pub_key = openssl::bn::BigNum::from_slice(pub_key_int.as_bytes())?;

let dsa = openssl::dsa::Dsa::from_public_components(p, q, g, pub_key)?;
Ok(openssl::pkey::PKey::from_dsa(dsa)?)
Ok(ParsedPublicKey::Pkey(openssl::pkey::PKey::from_dsa(dsa)?))
}
#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
AlgorithmParameters::Dh(dh_params) => {
Expand All @@ -85,7 +93,7 @@ pub fn parse_public_key(
let pub_key = openssl::bn::BigNum::from_slice(pub_key_int.as_bytes())?;
let dh = dh.set_public_key(pub_key)?;

Ok(openssl::pkey::PKey::from_dh(dh)?)
Ok(ParsedPublicKey::Pkey(openssl::pkey::PKey::from_dh(dh)?))
}
#[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))]
AlgorithmParameters::DhKeyAgreement(dh_params) => {
Expand All @@ -98,14 +106,16 @@ pub fn parse_public_key(
let pub_key = openssl::bn::BigNum::from_slice(pub_key_int.as_bytes())?;
let dh = dh.set_public_key(pub_key)?;

Ok(openssl::pkey::PKey::from_dh(dh)?)
Ok(ParsedPublicKey::Pkey(openssl::pkey::PKey::from_dh(dh)?))
}
#[cfg(CRYPTOGRAPHY_IS_AWSLC)]
AlgorithmParameters::MlDsa65 => Ok(cryptography_openssl::mldsa::new_raw_public_key(
cryptography_openssl::mldsa::MlDsaVariant::MlDsa65,
k.subject_public_key.as_bytes(),
)
.map_err(|_| KeyParsingError::InvalidKey)?),
AlgorithmParameters::MlDsa65 => Ok(ParsedPublicKey::Pkey(
cryptography_openssl::mldsa::new_raw_public_key(
cryptography_openssl::mldsa::MlDsaVariant::MlDsa65,
k.subject_public_key.as_bytes(),
)
.map_err(|_| KeyParsingError::InvalidKey)?,
)),

_ => Err(KeyParsingError::UnsupportedKeyType(
k.algorithm.oid().clone(),
Expand Down
Loading