Skip to content

Commit bbb1b35

Browse files
committed
Use the new OpenSSL 3.* API for managing EVP_PKEY
The OpenSSL 3.* users now do not have a way to use non-deprecated API by using this rust bindings, which is not sustainable in the long term as either distributions will stop building with the deprecated API or it will be eventually removed. This is now mostly PoC on using RSA keys using the new API. It does not expose OSSL_PARAM API as that is considered fragile. This is partially based on sfackler#2051 which was abandoned. Fixes: sfackler#2047 Signed-off-by: Jakub Jelen <[email protected]>
1 parent b621af1 commit bbb1b35

File tree

7 files changed

+464
-0
lines changed

7 files changed

+464
-0
lines changed

openssl-sys/src/core_dispatch.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use super::*;
2+
use libc::*;
3+
4+
/* OpenSSL 3.* only */
5+
6+
pub const OSSL_KEYMGMT_SELECT_PRIVATE_KEY: c_int = 0x01;
7+
pub const OSSL_KEYMGMT_SELECT_PUBLIC_KEY: c_int = 0x02;
8+
pub const OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: c_int = 0x04;
9+
pub const OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: c_int = 0x80;
10+
pub const OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: c_int =
11+
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;

openssl-sys/src/evp.rs

+9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9;
3838
pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10;
3939
pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11;
4040

41+
#[cfg(ossl300)]
42+
pub const EVP_PKEY_KEY_PARAMETERS: c_int = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
43+
#[cfg(ossl300)]
44+
pub const EVP_PKEY_PRIVATE_KEY: c_int = EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
45+
#[cfg(ossl300)]
46+
pub const EVP_PKEY_PUBLIC_KEY: c_int = EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
47+
#[cfg(ossl300)]
48+
pub const EVP_PKEY_KEYPAIR: c_int = EVP_PKEY_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
49+
4150
pub unsafe fn EVP_get_digestbynid(type_: c_int) -> *const EVP_MD {
4251
EVP_get_digestbyname(OBJ_nid2sn(type_))
4352
}

openssl-sys/src/handwritten/evp.rs

+27
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,27 @@ extern "C" {
489489
#[cfg(any(ossl110, libressl270))]
490490
pub fn EVP_PKEY_up_ref(pkey: *mut EVP_PKEY) -> c_int;
491491

492+
#[cfg(ossl300)]
493+
pub fn EVP_PKEY_fromdata_init(ctx: *mut EVP_PKEY_CTX) -> c_int;
494+
495+
#[cfg(ossl300)]
496+
pub fn EVP_PKEY_fromdata(
497+
ctx: *mut EVP_PKEY_CTX,
498+
ppkey: *mut *mut EVP_PKEY,
499+
selection: c_int,
500+
param: *mut OSSL_PARAM,
501+
) -> c_int;
502+
503+
#[cfg(ossl300)]
504+
pub fn EVP_PKEY_todata(
505+
ppkey: *const EVP_PKEY,
506+
selection: c_int,
507+
param: *mut *mut OSSL_PARAM,
508+
) -> c_int;
509+
510+
#[cfg(ossl300)]
511+
pub fn EVP_PKEY_generate(ctx: *mut EVP_PKEY_CTX, k: *mut *mut EVP_PKEY) -> c_int;
512+
492513
pub fn d2i_AutoPrivateKey(
493514
a: *mut *mut EVP_PKEY,
494515
pp: *mut *const c_uchar,
@@ -535,6 +556,12 @@ extern "C" {
535556

536557
pub fn EVP_PKEY_CTX_new(k: *mut EVP_PKEY, e: *mut ENGINE) -> *mut EVP_PKEY_CTX;
537558
pub fn EVP_PKEY_CTX_new_id(id: c_int, e: *mut ENGINE) -> *mut EVP_PKEY_CTX;
559+
#[cfg(ossl300)]
560+
pub fn EVP_PKEY_CTX_new_from_name(
561+
libctx: *mut OSSL_LIB_CTX,
562+
name: *const c_char,
563+
propquery: *const c_char,
564+
) -> *mut EVP_PKEY_CTX;
538565
pub fn EVP_PKEY_CTX_free(ctx: *mut EVP_PKEY_CTX);
539566

540567
pub fn EVP_PKEY_CTX_ctrl(

openssl-sys/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ mod openssl {
4242
pub use self::bio::*;
4343
pub use self::bn::*;
4444
pub use self::cms::*;
45+
#[cfg(ossl300)]
46+
pub use self::core_dispatch::*;
4547
pub use self::crypto::*;
4648
pub use self::dtls1::*;
4749
pub use self::ec::*;
@@ -72,6 +74,8 @@ mod openssl {
7274
mod bio;
7375
mod bn;
7476
mod cms;
77+
#[cfg(ossl300)]
78+
mod core_dispatch;
7579
mod crypto;
7680
mod dtls1;
7781
mod ec;

openssl/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ pub mod pkcs7;
186186
pub mod pkey;
187187
pub mod pkey_ctx;
188188
#[cfg(ossl300)]
189+
pub mod pkey_rsa;
190+
#[cfg(ossl300)]
189191
pub mod provider;
190192
pub mod rand;
191193
pub mod rsa;

openssl/src/pkey_ctx.rs

+56
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ let cmac_key = ctx.keygen().unwrap();
6767
#[cfg(not(boringssl))]
6868
use crate::cipher::CipherRef;
6969
use crate::error::ErrorStack;
70+
#[cfg(ossl300)]
71+
use crate::lib_ctx::LibCtxRef;
7072
use crate::md::MdRef;
7173
use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private};
7274
use crate::rsa::Padding;
@@ -81,6 +83,8 @@ use openssl_macros::corresponds;
8183
use std::convert::TryFrom;
8284
#[cfg(ossl320)]
8385
use std::ffi::CStr;
86+
#[cfg(ossl300)]
87+
use std::ffi::CString;
8488
use std::ptr;
8589

8690
/// HKDF modes of operation.
@@ -156,6 +160,26 @@ impl PkeyCtx<()> {
156160
Ok(PkeyCtx::from_ptr(ptr))
157161
}
158162
}
163+
164+
/// Creates a new pkey context from the algorithm name.
165+
#[corresponds(EVP_PKEY_CTX_new_from_name)]
166+
#[cfg(ossl300)]
167+
pub fn new_from_name(
168+
libctx: Option<&LibCtxRef>,
169+
name: &str,
170+
propquery: Option<&str>,
171+
) -> Result<Self, ErrorStack> {
172+
unsafe {
173+
let propquery = propquery.map(|s| CString::new(s).unwrap());
174+
let name = CString::new(name).unwrap();
175+
let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_from_name(
176+
libctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
177+
name.as_ptr(),
178+
propquery.map_or(ptr::null_mut(), |s| s.as_ptr()),
179+
))?;
180+
Ok(PkeyCtx::from_ptr(ptr))
181+
}
182+
}
159183
}
160184

161185
impl<T> PkeyCtxRef<T>
@@ -756,6 +780,20 @@ impl<T> PkeyCtxRef<T> {
756780
Ok(())
757781
}
758782

783+
/// Generates a new public/private keypair.
784+
///
785+
/// New OpenSSL 3.0 function, that should do the same thing as keygen()
786+
#[corresponds(EVP_PKEY_generate)]
787+
#[cfg(ossl300)]
788+
#[inline]
789+
pub fn generate(&mut self) -> Result<PKey<Private>, ErrorStack> {
790+
unsafe {
791+
let mut key = ptr::null_mut();
792+
cvt(ffi::EVP_PKEY_generate(self.as_ptr(), &mut key))?;
793+
Ok(PKey::from_ptr(key))
794+
}
795+
}
796+
759797
/// Gets the nonce type for a private key context.
760798
///
761799
/// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
@@ -780,6 +818,14 @@ impl<T> PkeyCtxRef<T> {
780818
}
781819
Ok(NonceType(nonce_type))
782820
}
821+
822+
/// Initializes a conversion from `OsslParam` to `PKey` on given `PkeyCtx`.
823+
#[corresponds(EVP_PKEY_fromdata_init)]
824+
#[cfg(ossl300)]
825+
pub fn fromdata_init(&mut self) -> Result<(), ErrorStack> {
826+
unsafe { cvt(ffi::EVP_PKEY_fromdata_init(self.as_ptr()))? };
827+
Ok(())
828+
}
783829
}
784830

785831
#[cfg(test)]
@@ -1107,4 +1153,14 @@ mxJ7imIrEg9nIQ==
11071153
assert_eq!(output, expected_output);
11081154
assert!(ErrorStack::get().errors().is_empty());
11091155
}
1156+
1157+
#[test]
1158+
#[cfg(ossl300)]
1159+
fn test_pkeyctx_from_name() {
1160+
let lib_ctx = crate::lib_ctx::LibCtx::new().unwrap();
1161+
let _: PkeyCtx<()> = PkeyCtx::new_from_name(Some(lib_ctx.as_ref()), "RSA", None).unwrap();
1162+
1163+
/* no libctx is ok */
1164+
let _: PkeyCtx<()> = PkeyCtx::new_from_name(None, "RSA", None).unwrap();
1165+
}
11101166
}

0 commit comments

Comments
 (0)