Skip to content

Commit 4e3eb68

Browse files
committed
crypto: Implement ECC key generation support
Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
1 parent 977ef7e commit 4e3eb68

File tree

1 file changed

+83
-3
lines changed

1 file changed

+83
-3
lines changed

keylime/src/crypto.rs

+83-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use base64::{engine::general_purpose, Engine as _};
55
use log::*;
66
use openssl::{
77
asn1::Asn1Time,
8+
ec::{EcGroupRef, EcKey},
89
encrypt::Decrypter,
910
hash::MessageDigest,
1011
memcmp,
@@ -49,6 +50,18 @@ pub enum CryptoError {
4950
#[error("failed to decrypt AES GCM encrypted data")]
5051
DecryptAEADError(#[source] openssl::error::ErrorStack),
5152

53+
/// Error obtaining generating EC private key
54+
#[error("failed to generate EC private key")]
55+
ECGeneratePrivateKeyError(#[source] openssl::error::ErrorStack),
56+
57+
/// Error obtaining EC private key from structure
58+
#[error("failed to get EC private key from structure")]
59+
ECGetPrivateKeyError(#[source] openssl::error::ErrorStack),
60+
61+
/// Error creating EcKey structure from public point
62+
#[error("failed to create EcKey structure from public point")]
63+
ECKeyFromPublicPointError(#[source] openssl::error::ErrorStack),
64+
5265
/// Error creating file
5366
#[error("failed to create file {file}")]
5467
FSCreateError {
@@ -99,6 +112,10 @@ pub enum CryptoError {
99112
#[error("failed to derive key from password with PBKDF2")]
100113
PBKDF2Error(#[source] openssl::error::ErrorStack),
101114

115+
/// Error creating PKey structure from EcKey structure
116+
#[error("failed to create PKey structure from EcKey structure")]
117+
PKeyFromEcKeyError(#[source] openssl::error::ErrorStack),
118+
102119
/// Error creating PKey structure from RSA structure
103120
#[error("failed to create PKey structure from RSA structure")]
104121
PKeyFromRSAError(#[source] openssl::error::ErrorStack),
@@ -577,11 +594,31 @@ fn rsa_generate(key_size: u32) -> Result<PKey<Private>, CryptoError> {
577594
.map_err(CryptoError::PKeyFromRSAError)
578595
}
579596

597+
/// Generate RSA key pair with the given size
598+
///
599+
/// Returns a tuple containing the PKey<Public> and PKey<Private>
580600
pub fn rsa_generate_pair(
581601
key_size: u32,
582602
) -> Result<(PKey<Public>, PKey<Private>), CryptoError> {
583603
let private = rsa_generate(key_size)?;
584604
let public = pkey_pub_from_priv(private.clone())?;
605+
606+
Ok((public, private))
607+
}
608+
609+
/// Generate a ECC key pair on given group
610+
///
611+
/// Returns a tuple containing the PKey<Public> and PKey<Private>
612+
pub fn ecc_generate_pair(
613+
group: &EcGroupRef,
614+
) -> Result<(PKey<Public>, PKey<Private>), CryptoError> {
615+
let private = PKey::from_ec_key(
616+
EcKey::generate(group)
617+
.map_err(CryptoError::ECGeneratePrivateKeyError)?,
618+
)
619+
.map_err(CryptoError::PKeyFromEcKeyError)?;
620+
let public = pkey_pub_from_priv(private.clone())?;
621+
585622
Ok((public, private))
586623
}
587624

@@ -607,6 +644,17 @@ fn pkey_pub_from_priv(
607644
.map_err(CryptoError::RSAFromComponents)?;
608645
PKey::from_rsa(rsa).map_err(CryptoError::PKeyFromRSAError)
609646
}
647+
Id::EC => {
648+
let ec_key = privkey
649+
.ec_key()
650+
.map_err(CryptoError::ECGetPrivateKeyError)?;
651+
652+
let pubkey =
653+
EcKey::from_public_key(ec_key.group(), ec_key.public_key())
654+
.map_err(CryptoError::ECKeyFromPublicPointError)?;
655+
656+
PKey::from_ec_key(pubkey).map_err(CryptoError::PKeyFromEcKeyError)
657+
}
610658
id => Err(CryptoError::UnsupportedKeyAlgorithm {
611659
id: format!("{id:?}"),
612660
}),
@@ -1426,8 +1474,16 @@ mod tests {
14261474
let cert = r.unwrap(); //#[allow_ci]
14271475

14281476
// Test getting public key from cert
1429-
let r = x509_get_pubkey(&cert);
1430-
assert!(r.is_ok());
1477+
let pubkey_from_cert = x509_get_pubkey(&cert)
1478+
.expect("Failed to get public key from certificate");
1479+
assert_eq!(
1480+
pubkey
1481+
.public_key_to_der()
1482+
.expect("Failed to convert public key to DER"),
1483+
pubkey_from_cert
1484+
.public_key_to_der()
1485+
.expect("Failed to convert public key to DER")
1486+
);
14311487

14321488
// Test converting certificate to DER
14331489
let r = x509_to_der(&cert);
@@ -1467,10 +1523,34 @@ mod tests {
14671523
#[test]
14681524
fn test_x509_rsa() {
14691525
let (pubkey, privkey) = rsa_generate_pair(2048).unwrap(); //#[allow_ci]
1470-
14711526
test_x509(privkey, pubkey);
14721527
}
14731528

1529+
#[test]
1530+
#[ignore]
1531+
fn test_x509_long_rsa() {
1532+
for length in [3072, 4096] {
1533+
let (pubkey, privkey) = rsa_generate_pair(length).unwrap(); //#[allow_ci]
1534+
test_x509(privkey, pubkey);
1535+
}
1536+
}
1537+
1538+
#[test]
1539+
fn test_x509_ecc() {
1540+
use openssl::ec::EcGroup;
1541+
1542+
for group in [
1543+
EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(), //#[allow_ci]
1544+
EcGroup::from_curve_name(Nid::SECP256K1).unwrap(), //#[allow_ci]
1545+
EcGroup::from_curve_name(Nid::SECP384R1).unwrap(), //#[allow_ci],
1546+
EcGroup::from_curve_name(Nid::SECP521R1).unwrap(), //#[allow_ci]
1547+
] {
1548+
let (pubkey, privkey) = ecc_generate_pair(&group).unwrap(); //#[allow_ci]
1549+
1550+
test_x509(privkey, pubkey);
1551+
}
1552+
}
1553+
14741554
#[test]
14751555
fn test_match_cert_to_template() {
14761556
for (file_name, template) in

0 commit comments

Comments
 (0)