Skip to content

Commit 63196e6

Browse files
authored
Merge pull request #2431 from huwcbjones/huw/pkey-ctx-rsa-keygen
pkey_ctx: add ability to generate RSA keys
2 parents fcf0cf9 + a51da3d commit 63196e6

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

openssl-sys/src/handwritten/rsa.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ use libc::*;
44
cfg_if! {
55
if #[cfg(ossl300)] {
66
extern "C" {
7+
pub fn EVP_PKEY_CTX_set_rsa_keygen_bits(ctx: *mut EVP_PKEY_CTX, bits: c_int) -> c_int;
8+
pub fn EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx: *mut EVP_PKEY_CTX, pubexp: *mut BIGNUM) -> c_int;
9+
710
pub fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad_mode: c_int) -> c_int;
811
pub fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad_mode: *mut c_int) -> c_int;
912

openssl-sys/src/rsa.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ pub const RSA_F4: c_long = 0x10001;
77

88
cfg_if! {
99
if #[cfg(not(ossl300))] {
10+
pub unsafe fn EVP_PKEY_CTX_set_rsa_keygen_bits(ctx: *mut EVP_PKEY_CTX, bits: c_int) -> c_int {
11+
EVP_PKEY_CTX_ctrl(
12+
ctx,
13+
EVP_PKEY_RSA,
14+
EVP_PKEY_OP_KEYGEN,
15+
EVP_PKEY_CTRL_RSA_KEYGEN_BITS,
16+
bits,
17+
ptr::null_mut(),
18+
)
19+
}
20+
pub unsafe fn EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx: *mut EVP_PKEY_CTX, pubexp: *mut BIGNUM) -> c_int {
21+
EVP_PKEY_CTX_ctrl(
22+
ctx,
23+
EVP_PKEY_RSA,
24+
EVP_PKEY_OP_KEYGEN,
25+
EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP,
26+
0,
27+
pubexp as *mut _,
28+
)
29+
}
1030
pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int {
1131
EVP_PKEY_CTX_ctrl(
1232
ctx,
@@ -82,6 +102,8 @@ pub unsafe fn EVP_PKEY_CTX_set0_rsa_oaep_label(
82102

83103
pub const EVP_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1;
84104
pub const EVP_PKEY_CTRL_RSA_PSS_SALTLEN: c_int = EVP_PKEY_ALG_CTRL + 2;
105+
pub const EVP_PKEY_CTRL_RSA_KEYGEN_BITS: c_int = EVP_PKEY_ALG_CTRL + 3;
106+
pub const EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: c_int = EVP_PKEY_ALG_CTRL + 4;
85107

86108
pub const EVP_PKEY_CTRL_RSA_MGF1_MD: c_int = EVP_PKEY_ALG_CTRL + 5;
87109

openssl/src/pkey_ctx.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ let cmac_key = ctx.keygen().unwrap();
6464
//! let valid = ctx.verify(text, &signature).unwrap();
6565
//! assert!(valid);
6666
//! ```
67+
use crate::bn::BigNumRef;
6768
#[cfg(not(any(boringssl, awslc)))]
6869
use crate::cipher::CipherRef;
6970
use crate::error::ErrorStack;
@@ -73,6 +74,7 @@ use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Params, Private};
7374
use crate::rsa::Padding;
7475
use crate::sign::RsaPssSaltlen;
7576
use crate::{cvt, cvt_p};
77+
use cfg_if::cfg_if;
7678
use foreign_types::{ForeignType, ForeignTypeRef};
7779
#[cfg(not(any(boringssl, awslc)))]
7880
use libc::c_int;
@@ -544,6 +546,48 @@ impl<T> PkeyCtxRef<T> {
544546
Ok(())
545547
}
546548

549+
/// Sets the RSA keygen bits.
550+
///
551+
/// This is only useful for RSA keys.
552+
#[corresponds(EVP_PKEY_CTX_set_rsa_keygen_bits)]
553+
#[inline]
554+
pub fn set_rsa_keygen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
555+
unsafe {
556+
cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_bits(
557+
self.as_ptr(),
558+
bits as i32,
559+
))?;
560+
}
561+
562+
Ok(())
563+
}
564+
565+
/// Sets the RSA keygen public exponent.
566+
///
567+
/// This is only useful for RSA keys.
568+
#[corresponds(EVP_PKEY_CTX_set1_rsa_keygen_pubexp)]
569+
#[inline]
570+
pub fn set_rsa_keygen_pubexp(&mut self, pubexp: &BigNumRef) -> Result<(), ErrorStack> {
571+
unsafe {
572+
cfg_if! {
573+
if #[cfg(ossl300)] {
574+
cvt(ffi::EVP_PKEY_CTX_set1_rsa_keygen_pubexp(
575+
self.as_ptr(),
576+
pubexp.as_ptr(),
577+
))?;
578+
} else {
579+
cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_pubexp(
580+
self.as_ptr(),
581+
// Dupe the BN because the EVP_PKEY_CTX takes ownership of it and will free it.
582+
cvt_p(ffi::BN_dup(pubexp.as_ptr()))?,
583+
))?;
584+
}
585+
}
586+
}
587+
588+
Ok(())
589+
}
590+
547591
/// Sets the RSA PSS salt length.
548592
///
549593
/// This is only useful for RSA keys.
@@ -874,6 +918,7 @@ impl<T> PkeyCtxRef<T> {
874918
#[cfg(test)]
875919
mod test {
876920
use super::*;
921+
use crate::bn::BigNum;
877922
#[cfg(not(any(boringssl, awslc)))]
878923
use crate::cipher::Cipher;
879924
use crate::ec::{EcGroup, EcKey};
@@ -1057,6 +1102,18 @@ mod test {
10571102
assert_eq!(params.size(), 72);
10581103
}
10591104

1105+
#[test]
1106+
fn rsa_keygen() {
1107+
let pubexp = BigNum::from_u32(65537).unwrap();
1108+
let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap();
1109+
ctx.keygen_init().unwrap();
1110+
ctx.set_rsa_keygen_pubexp(&pubexp).unwrap();
1111+
ctx.set_rsa_keygen_bits(2048).unwrap();
1112+
let key = ctx.keygen().unwrap();
1113+
1114+
assert_eq!(key.bits(), 2048);
1115+
}
1116+
10601117
#[test]
10611118
#[cfg(any(ossl110, boringssl, libressl360, awslc))]
10621119
fn hkdf() {

0 commit comments

Comments
 (0)