Skip to content

Add ability to create PKey from parameters #2439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openssl-sys/build/run_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const INCLUDES: &str = "

#if OPENSSL_VERSION_NUMBER >= 0x30000000
#include <openssl/provider.h>
#include <openssl/params.h>
#include <openssl/param_build.h>
#endif

#if OPENSSL_VERSION_NUMBER >= 0x30200000
Expand Down
24 changes: 24 additions & 0 deletions openssl-sys/src/evp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,27 @@ pub unsafe fn EVP_PKEY_assign_DH(pkey: *mut EVP_PKEY, dh: *mut DH) -> c_int {
pub unsafe fn EVP_PKEY_assign_EC_KEY(pkey: *mut EVP_PKEY, ec_key: *mut EC_KEY) -> c_int {
EVP_PKEY_assign(pkey, EVP_PKEY_EC, ec_key as *mut c_void)
}

cfg_if! {
if #[cfg(ossl300)] {
// consts required for EVP_PKEY_fromdata selection value

// From <openssl/core_dispatch.h>
const OSSL_KEYMGMT_SELECT_PRIVATE_KEY: c_int = 0x01;
const OSSL_KEYMGMT_SELECT_PUBLIC_KEY: c_int = 0x02;
const OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: c_int = 0x04;
const OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: c_int = 0x80;
const OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: c_int =
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
const OSSL_KEYMGMT_SELECT_KEYPAIR: c_int =
OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
const OSSL_KEYMGMT_SELECT_ALL: c_int =
OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;

// From <openssl/evp.h>
pub const EVP_PKEY_KEY_PARAMETERS: c_int = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
pub const EVP_PKEY_PRIVATE_KEY: c_int = EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
pub const EVP_PKEY_PUBLIC_KEY: c_int = EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
pub const EVP_PKEY_KEYPAIR: c_int = EVP_PKEY_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
}
}
10 changes: 10 additions & 0 deletions openssl-sys/src/handwritten/evp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,16 @@ extern "C" {
pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int;
pub fn EVP_PKEY_paramgen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int;

#[cfg(ossl300)]
pub fn EVP_PKEY_fromdata_init(ctx: *mut EVP_PKEY_CTX) -> c_int;
#[cfg(ossl300)]
pub fn EVP_PKEY_fromdata(
ctx: *mut EVP_PKEY_CTX,
ppkey: *mut *mut EVP_PKEY,
selection: c_int,
params: *mut OSSL_PARAM,
) -> c_int;

pub fn EVP_PKEY_sign_init(ctx: *mut EVP_PKEY_CTX) -> c_int;
pub fn EVP_PKEY_sign(
ctx: *mut EVP_PKEY_CTX,
Expand Down
63 changes: 60 additions & 3 deletions openssl-sys/src/handwritten/params.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,73 @@
use super::super::*;
use libc::*;

#[cfg(ossl300)]
extern "C" {
#[cfg(ossl300)]
pub fn OSSL_PARAM_dup(params: *const OSSL_PARAM) -> *mut OSSL_PARAM;
pub fn OSSL_PARAM_free(params: *mut OSSL_PARAM);
pub fn OSSL_PARAM_merge(
params: *const OSSL_PARAM,
params1: *const OSSL_PARAM,
) -> *mut OSSL_PARAM;
pub fn OSSL_PARAM_locate(params: *mut OSSL_PARAM, key: *const c_char) -> *mut OSSL_PARAM;
pub fn OSSL_PARAM_locate_const(
params: *const OSSL_PARAM,
key: *const c_char,
) -> *const OSSL_PARAM;
pub fn OSSL_PARAM_construct_uint(key: *const c_char, buf: *mut c_uint) -> OSSL_PARAM;
#[cfg(ossl300)]
pub fn OSSL_PARAM_construct_end() -> OSSL_PARAM;
#[cfg(ossl300)]
pub fn OSSL_PARAM_construct_octet_string(
key: *const c_char,
buf: *mut c_void,
bsize: size_t,
) -> OSSL_PARAM;

pub fn OSSL_PARAM_BLD_new() -> *mut OSSL_PARAM_BLD;
pub fn OSSL_PARAM_BLD_free(bld: *mut OSSL_PARAM_BLD);
pub fn OSSL_PARAM_BLD_to_param(bld: *mut OSSL_PARAM_BLD) -> *mut OSSL_PARAM;
pub fn OSSL_PARAM_BLD_push_uint(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
val: c_uint,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_size_t(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
val: size_t,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_BN(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
bn: *const BIGNUM,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_BN_pad(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
bn: *const BIGNUM,
sz: size_t,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_utf8_string(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
buf: *const c_char,
bsize: size_t,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_utf8_ptr(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
buf: *mut c_char,
bsize: size_t,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_octet_string(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
buf: *const c_void,
bsize: size_t,
) -> c_int;
pub fn OSSL_PARAM_BLD_push_octet_ptr(
bld: *mut OSSL_PARAM_BLD,
key: *const c_char,
buf: *mut c_void,
bsize: size_t,
) -> c_int;
}
5 changes: 4 additions & 1 deletion openssl-sys/src/handwritten/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,12 +1134,15 @@ pub enum OSSL_LIB_CTX {}
#[repr(C)]
pub struct OSSL_PARAM {
key: *const c_char,
data_type: c_uchar,
data_type: c_uint,
data: *mut c_void,
data_size: size_t,
return_size: size_t,
}

#[cfg(ossl300)]
pub enum OSSL_PARAM_BLD {}

#[cfg(ossl300)]
pub enum EVP_KDF {}
#[cfg(ossl300)]
Expand Down
117 changes: 40 additions & 77 deletions openssl/src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ impl Drop for EvpKdfCtx {
cfg_if::cfg_if! {
if #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] {
use std::cmp;
use std::ffi::c_void;
use std::ffi::CStr;
use std::mem::MaybeUninit;
use std::ptr;
use foreign_types::ForeignTypeRef;
use libc::c_char;
use crate::{cvt, cvt_p};
use crate::lib_ctx::LibCtxRef;
use crate::error::ErrorStack;
use crate::params::ParamBuilder;
use crate::util::c_str;

#[allow(clippy::too_many_arguments)]
pub fn argon2d(
Expand Down Expand Up @@ -94,86 +93,50 @@ cfg_if::cfg_if! {
salt: &[u8],
ad: Option<&[u8]>,
secret: Option<&[u8]>,
mut iter: u32,
mut lanes: u32,
mut memcost: u32,
iter: u32,
lanes: u32,
memcost: u32,
out: &mut [u8],
) -> Result<(), ErrorStack> {
unsafe {
ffi::init();
let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr);

let max_threads = ffi::OSSL_get_max_threads(libctx);
let mut threads = 1;
// If max_threads is 0, then this isn't a threaded build.
// If max_threads is > u32::MAX we need to clamp since
// argon2's threads parameter is a u32.
if max_threads > 0 {
threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32);
}
let mut params: [ffi::OSSL_PARAM; 10] =
core::array::from_fn(|_| MaybeUninit::<ffi::OSSL_PARAM>::zeroed().assume_init());
let mut idx = 0;
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
b"pass\0".as_ptr() as *const c_char,
pass.as_ptr() as *mut c_void,
pass.len(),
);
idx += 1;
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
b"salt\0".as_ptr() as *const c_char,
salt.as_ptr() as *mut c_void,
salt.len(),
);
idx += 1;
params[idx] =
ffi::OSSL_PARAM_construct_uint(b"threads\0".as_ptr() as *const c_char, &mut threads);
idx += 1;
params[idx] =
ffi::OSSL_PARAM_construct_uint(b"lanes\0".as_ptr() as *const c_char, &mut lanes);
idx += 1;
params[idx] =
ffi::OSSL_PARAM_construct_uint(b"memcost\0".as_ptr() as *const c_char, &mut memcost);
idx += 1;
params[idx] =
ffi::OSSL_PARAM_construct_uint(b"iter\0".as_ptr() as *const c_char, &mut iter);
idx += 1;
let mut size = out.len() as u32;
params[idx] =
ffi::OSSL_PARAM_construct_uint(b"size\0".as_ptr() as *const c_char, &mut size);
idx += 1;
if let Some(ad) = ad {
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
b"ad\0".as_ptr() as *const c_char,
ad.as_ptr() as *mut c_void,
ad.len(),
);
idx += 1;
}
if let Some(secret) = secret {
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
b"secret\0".as_ptr() as *const c_char,
secret.as_ptr() as *mut c_void,
secret.len(),
);
idx += 1;
}
params[idx] = ffi::OSSL_PARAM_construct_end();
ffi::init();
let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr);

let max_threads = unsafe { ffi::OSSL_get_max_threads(libctx) };
let mut threads = 1;
// If max_threads is 0, then this isn't a threaded build.
// If max_threads is > u32::MAX we need to clamp since
// argon2's threads parameter is a u32.
if max_threads > 0 {
threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32);
}
let mut param_builder = ParamBuilder::new()
.push_byte_string(c_str(b"pass\0"), pass)?
.push_byte_string(c_str(b"salt\0"), salt)?
.push_uint(c_str(b"threads\0"), threads)?
.push_uint(c_str(b"lanes\0"), lanes)?
.push_uint(c_str(b"memcost\0"), memcost)?
.push_uint(c_str(b"iter\0"), iter)?
.push_size_t(c_str(b"size\0"), out.len())?;
if let Some(ad) = ad {
param_builder = param_builder.push_byte_string(c_str(b"ad\0"), ad)?;
}
if let Some(secret) = secret {
param_builder = param_builder.push_byte_string(c_str(b"secret\0"), secret)?;
}

let argon2 = EvpKdf(cvt_p(ffi::EVP_KDF_fetch(
libctx,
kdf_identifier.as_ptr() as *const c_char,
ptr::null(),
))?);
let ctx = EvpKdfCtx(cvt_p(ffi::EVP_KDF_CTX_new(argon2.0))?);
cvt(ffi::EVP_KDF_derive(
let argon2 = EvpKdf(cvt_p(unsafe {
ffi::EVP_KDF_fetch(libctx, kdf_identifier.as_ptr(), ptr::null())
})?);
let ctx = EvpKdfCtx(cvt_p(unsafe { ffi::EVP_KDF_CTX_new(argon2.0) })?);
cvt(unsafe {
ffi::EVP_KDF_derive(
ctx.0,
out.as_mut_ptr(),
out.len(),
params.as_ptr(),
))
.map(|_| ())
}
param_builder.build()?.as_ptr(),
)
})
.map(|_| ())
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions openssl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ pub mod memcmp;
pub mod nid;
#[cfg(not(osslconf = "OPENSSL_NO_OCSP"))]
pub mod ocsp;
#[cfg(ossl300)]
mod params;
pub mod pkcs12;
pub mod pkcs5;
#[cfg(not(any(boringssl, awslc)))]
Expand Down
Loading
Loading