Skip to content

Commit 54d5669

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
1 parent 82b958c commit 54d5669

File tree

13 files changed

+582
-4
lines changed

13 files changed

+582
-4
lines changed

openssl-sys/build/run_bindgen.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const INCLUDES: &str = "
5353
#endif
5454
5555
#if OPENSSL_VERSION_NUMBER >= 0x30000000
56+
#include <openssl/param_build.h>
5657
#include <openssl/provider.h>
5758
#endif
5859

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/handwritten/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub use self::hmac::*;
1515
pub use self::kdf::*;
1616
pub use self::object::*;
1717
pub use self::ocsp::*;
18+
#[cfg(ossl300)]
19+
pub use self::param_build::*;
20+
#[cfg(ossl300)]
1821
pub use self::params::*;
1922
pub use self::pem::*;
2023
pub use self::pkcs12::*;
@@ -54,6 +57,9 @@ mod hmac;
5457
mod kdf;
5558
mod object;
5659
mod ocsp;
60+
#[cfg(ossl300)]
61+
mod param_build;
62+
#[cfg(ossl300)]
5763
mod params;
5864
mod pem;
5965
mod pkcs12;
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use super::super::*;
2+
use libc::*;
3+
4+
/* OpenSSL 3.* only */
5+
6+
extern "C" {
7+
pub fn OSSL_PARAM_BLD_new() -> *mut OSSL_PARAM_BLD;
8+
pub fn OSSL_PARAM_BLD_free(bld: *mut OSSL_PARAM_BLD);
9+
pub fn OSSL_PARAM_BLD_push_BN(
10+
bld: *mut OSSL_PARAM_BLD,
11+
key: *const c_char,
12+
bn: *const BIGNUM,
13+
) -> c_int;
14+
pub fn OSSL_PARAM_BLD_push_utf8_string(
15+
bld: *mut OSSL_PARAM_BLD,
16+
key: *const c_char,
17+
buf: *const c_char,
18+
bsize: usize,
19+
) -> c_int;
20+
pub fn OSSL_PARAM_BLD_push_octet_string(
21+
bld: *mut OSSL_PARAM_BLD,
22+
key: *const c_char,
23+
buf: *const c_void,
24+
bsize: usize,
25+
) -> c_int;
26+
pub fn OSSL_PARAM_BLD_push_uint(
27+
bld: *mut OSSL_PARAM_BLD,
28+
key: *const c_char,
29+
buf: c_uint,
30+
) -> c_int;
31+
pub fn OSSL_PARAM_BLD_to_param(bld: *mut OSSL_PARAM_BLD) -> *mut OSSL_PARAM;
32+
}

openssl-sys/src/handwritten/params.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,32 @@ use super::super::*;
22
use libc::*;
33

44
extern "C" {
5-
#[cfg(ossl300)]
5+
pub fn OSSL_PARAM_free(p: *mut OSSL_PARAM);
66
pub fn OSSL_PARAM_construct_uint(key: *const c_char, buf: *mut c_uint) -> OSSL_PARAM;
7-
#[cfg(ossl300)]
87
pub fn OSSL_PARAM_construct_end() -> OSSL_PARAM;
9-
#[cfg(ossl300)]
108
pub fn OSSL_PARAM_construct_octet_string(
119
key: *const c_char,
1210
buf: *mut c_void,
1311
bsize: size_t,
1412
) -> OSSL_PARAM;
1513

14+
pub fn OSSL_PARAM_locate(p: *mut OSSL_PARAM, key: *const c_char) -> *mut OSSL_PARAM;
15+
pub fn OSSL_PARAM_get_BN(p: *const OSSL_PARAM, val: *mut *mut BIGNUM) -> c_int;
16+
pub fn OSSL_PARAM_get_utf8_string(
17+
p: *const OSSL_PARAM,
18+
val: *mut *mut c_char,
19+
max_len: usize,
20+
) -> c_int;
21+
pub fn OSSL_PARAM_get_utf8_string_ptr(p: *const OSSL_PARAM, val: *mut *const c_char) -> c_int;
22+
pub fn OSSL_PARAM_get_octet_string(
23+
p: *const OSSL_PARAM,
24+
val: *mut *mut c_void,
25+
max_len: usize,
26+
used_len: *mut usize,
27+
) -> c_int;
28+
pub fn OSSL_PARAM_get_octet_string_ptr(
29+
p: *const OSSL_PARAM,
30+
val: *mut *const c_void,
31+
used_len: *mut usize,
32+
) -> c_int;
1633
}

openssl-sys/src/handwritten/types.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,9 @@ pub struct OSSL_PARAM {
11401140
return_size: size_t,
11411141
}
11421142

1143+
#[cfg(ossl300)]
1144+
pub enum OSSL_PARAM_BLD {}
1145+
11431146
#[cfg(ossl300)]
11441147
pub enum EVP_KDF {}
11451148
#[cfg(ossl300)]

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
@@ -184,6 +184,8 @@ pub mod pkcs7;
184184
pub mod pkey;
185185
pub mod pkey_ctx;
186186
#[cfg(ossl300)]
187+
pub mod pkey_rsa;
188+
#[cfg(ossl300)]
187189
pub mod provider;
188190
pub mod rand;
189191
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 `OsllParam` 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)