@@ -5,6 +5,7 @@ use base64::{engine::general_purpose, Engine as _};
5
5
use log:: * ;
6
6
use openssl:: {
7
7
asn1:: Asn1Time ,
8
+ ec:: { EcGroupRef , EcKey } ,
8
9
encrypt:: Decrypter ,
9
10
hash:: MessageDigest ,
10
11
memcmp,
@@ -49,6 +50,18 @@ pub enum CryptoError {
49
50
#[ error( "failed to decrypt AES GCM encrypted data" ) ]
50
51
DecryptAEADError ( #[ source] openssl:: error:: ErrorStack ) ,
51
52
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
+
52
65
/// Error creating file
53
66
#[ error( "failed to create file {file}" ) ]
54
67
FSCreateError {
@@ -99,6 +112,10 @@ pub enum CryptoError {
99
112
#[ error( "failed to derive key from password with PBKDF2" ) ]
100
113
PBKDF2Error ( #[ source] openssl:: error:: ErrorStack ) ,
101
114
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
+
102
119
/// Error creating PKey structure from RSA structure
103
120
#[ error( "failed to create PKey structure from RSA structure" ) ]
104
121
PKeyFromRSAError ( #[ source] openssl:: error:: ErrorStack ) ,
@@ -577,11 +594,31 @@ fn rsa_generate(key_size: u32) -> Result<PKey<Private>, CryptoError> {
577
594
. map_err ( CryptoError :: PKeyFromRSAError )
578
595
}
579
596
597
+ /// Generate RSA key pair with the given size
598
+ ///
599
+ /// Returns a tuple containing the PKey<Public> and PKey<Private>
580
600
pub fn rsa_generate_pair (
581
601
key_size : u32 ,
582
602
) -> Result < ( PKey < Public > , PKey < Private > ) , CryptoError > {
583
603
let private = rsa_generate ( key_size) ?;
584
604
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
+
585
622
Ok ( ( public, private) )
586
623
}
587
624
@@ -607,6 +644,17 @@ fn pkey_pub_from_priv(
607
644
. map_err ( CryptoError :: RSAFromComponents ) ?;
608
645
PKey :: from_rsa ( rsa) . map_err ( CryptoError :: PKeyFromRSAError )
609
646
}
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
+ }
610
658
id => Err ( CryptoError :: UnsupportedKeyAlgorithm {
611
659
id : format ! ( "{id:?}" ) ,
612
660
} ) ,
@@ -1426,8 +1474,16 @@ mod tests {
1426
1474
let cert = r. unwrap ( ) ; //#[allow_ci]
1427
1475
1428
1476
// 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
+ ) ;
1431
1487
1432
1488
// Test converting certificate to DER
1433
1489
let r = x509_to_der ( & cert) ;
@@ -1467,10 +1523,34 @@ mod tests {
1467
1523
#[ test]
1468
1524
fn test_x509_rsa ( ) {
1469
1525
let ( pubkey, privkey) = rsa_generate_pair ( 2048 ) . unwrap ( ) ; //#[allow_ci]
1470
-
1471
1526
test_x509 ( privkey, pubkey) ;
1472
1527
}
1473
1528
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
+
1474
1554
#[ test]
1475
1555
fn test_match_cert_to_template ( ) {
1476
1556
for ( file_name, template) in
0 commit comments