Skip to content

Commit 7ceae78

Browse files
Jakujeteythoon
authored andcommitted
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 partially based on sfackler#2051 which was abandoned. Signed-off-by: Jakub Jelen <[email protected]>
1 parent 88e9baa commit 7ceae78

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

openssl-sys/src/core_dispatch.rs

Lines changed: 11 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 27 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ mod openssl {
6969
pub use self::bio::*;
7070
pub use self::bn::*;
7171
pub use self::cms::*;
72+
#[cfg(ossl300)]
73+
pub use self::core_dispatch::*;
7274
pub use self::crypto::*;
7375
pub use self::dtls1::*;
7476
pub use self::ec::*;
@@ -99,6 +101,8 @@ mod openssl {
99101
mod bio;
100102
mod bn;
101103
mod cms;
104+
#[cfg(ossl300)]
105+
mod core_dispatch;
102106
mod crypto;
103107
mod dtls1;
104108
mod ec;

openssl/src/pkey_ctx.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ let cmac_key = ctx.keygen().unwrap();
6767
#[cfg(not(any(boringssl, awslc)))]
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)