-
-
Notifications
You must be signed in to change notification settings - Fork 790
ML-KEM/ML-DSA part 2: param builder #2451
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
base: master
Are you sure you want to change the base?
Changes from 6 commits
69182d1
00e12f7
131cddd
6e4440f
7642cc6
99520b0
20091b3
deae632
21a83a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
//! OSSL_PARAM management for OpenSSL 3.* | ||
//! | ||
//! The OSSL_PARAM structure represents an array of generic | ||
//! attributes that can represent various | ||
//! properties in OpenSSL, including keys and operations. | ||
//! | ||
//! This is always represented as an array of OSSL_PARAM | ||
//! structures, terminated by an entry with a NULL key. | ||
//! | ||
//! For convinience, the OSSL_PARAM_BLD builder can be used to | ||
//! dynamically construct these structures. | ||
//! | ||
//! Note, that this module is available only in OpenSSL 3.* and | ||
//! only internally for this crate. | ||
|
||
use crate::bn::{BigNum, BigNumRef}; | ||
use crate::error::ErrorStack; | ||
use crate::util; | ||
use crate::{cvt, cvt_p}; | ||
use foreign_types::{ForeignType, ForeignTypeRef}; | ||
use libc::{c_char, c_uint, c_void}; | ||
use openssl_macros::corresponds; | ||
use std::ffi::CStr; | ||
use std::ptr; | ||
|
||
foreign_type_and_impl_send_sync! { | ||
// This is the singular type, but it is always allocated | ||
// and used as an array of such types. | ||
type CType = ffi::OSSL_PARAM; | ||
// OSSL_PARMA_free correctly frees the entire array. | ||
fn drop = ffi::OSSL_PARAM_free; | ||
|
||
/// `OsslParamArray` constructed using `OsslParamBuilder`. | ||
/// Internally this is a pointer to an array of the OSSL_PARAM | ||
/// structures. | ||
pub struct OsslParamArray; | ||
/// Reference to `OsslParamArray`. | ||
pub struct OsslParamArrayRef; | ||
} | ||
|
||
impl OsslParamArrayRef { | ||
/// Locates the individual `OSSL_PARAM` element identified by the key | ||
/// in the `OsslParamArray` array and returns a reference | ||
/// to it. | ||
#[corresponds(OSSL_PARAM_locate)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn locate(&self, key: &CStr) -> Result<&OsslParamArrayRef, ErrorStack> { | ||
unsafe { | ||
let param = cvt_p(ffi::OSSL_PARAM_locate(self.as_ptr(), key.as_ptr()))?; | ||
Ok(OsslParamArrayRef::from_ptr(param)) | ||
} | ||
} | ||
|
||
/// Get `BigNum` from the current OSSL_PARAM at the top of this | ||
/// `OsslParamArray` reference. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this is a useful behavior -- I think we really need separate types for these. (I think it logically follows that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gotcha. I’ll think on that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I separated out the overall OSSL_PARAM array and added a separate struct for an interior individual OSSL_PARAM struct (wrapping an internal reference tied to the lifetime over the entire array). I think this should be cleaner. |
||
#[corresponds(OSSL_PARAM_get_BN)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn get_bn(&self) -> Result<BigNum, ErrorStack> { | ||
unsafe { | ||
let mut bn: *mut ffi::BIGNUM = ptr::null_mut(); | ||
cvt(ffi::OSSL_PARAM_get_BN(self.as_ptr(), &mut bn))?; | ||
Ok(BigNum::from_ptr(bn)) | ||
} | ||
} | ||
|
||
/// Get `&str` from the current OSSL_PARAM at the top of this | ||
/// `OsslParamArray` reference. | ||
#[corresponds(OSSL_PARAM_get_utf8_string)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn get_utf8_string(&self) -> Result<&str, ErrorStack> { | ||
unsafe { | ||
let mut val: *const c_char = ptr::null_mut(); | ||
cvt(ffi::OSSL_PARAM_get_utf8_string_ptr(self.as_ptr(), &mut val))?; | ||
Ok(CStr::from_ptr(val).to_str().unwrap()) | ||
} | ||
} | ||
|
||
/// Get octet string (as `&[u8]) from the current OSSL_PARAM at the | ||
/// top of this `OsslParamArray` reference. | ||
#[corresponds(OSSL_PARAM_get_octet_string)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn get_octet_string(&self) -> Result<&[u8], ErrorStack> { | ||
unsafe { | ||
let mut val: *const c_void = ptr::null_mut(); | ||
let mut val_len: usize = 0; | ||
cvt(ffi::OSSL_PARAM_get_octet_string_ptr( | ||
self.as_ptr(), | ||
&mut val, | ||
&mut val_len, | ||
))?; | ||
Ok(util::from_raw_parts(val as *const u8, val_len)) | ||
} | ||
} | ||
} | ||
|
||
foreign_type_and_impl_send_sync! { | ||
type CType = ffi::OSSL_PARAM_BLD; | ||
fn drop = ffi::OSSL_PARAM_BLD_free; | ||
|
||
/// Builder used to construct `OsslParamArray`. | ||
pub struct OsslParamBuilder; | ||
/// Reference to `OsslParamBuilder`. | ||
pub struct OsslParamBuilderRef; | ||
} | ||
|
||
impl OsslParamBuilder { | ||
/// Returns a builder for an OsslParamArray. | ||
/// | ||
/// The array is initially empty. | ||
#[corresponds(OSSL_PARAM_BLD_new)] | ||
#[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] | ||
pub(crate) fn new() -> Result<OsslParamBuilder, ErrorStack> { | ||
unsafe { | ||
ffi::init(); | ||
|
||
cvt_p(ffi::OSSL_PARAM_BLD_new()).map(OsslParamBuilder) | ||
} | ||
} | ||
|
||
/// Constructs the `OsslParamArray` and clears this builder. | ||
#[corresponds(OSSL_PARAM_BLD_to_param)] | ||
#[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] | ||
#[allow(clippy::wrong_self_convention)] | ||
pub(crate) fn to_param(&mut self) -> Result<OsslParamArray, ErrorStack> { | ||
unsafe { | ||
let params = cvt_p(ffi::OSSL_PARAM_BLD_to_param(self.0))?; | ||
Ok(OsslParamArray::from_ptr(params)) | ||
} | ||
} | ||
} | ||
|
||
impl OsslParamBuilderRef { | ||
/// Adds a `BigNum` to `OsslParamBuilder`. | ||
/// | ||
/// Note, that both key and bn need to exist until the `to_param` is called! | ||
#[corresponds(OSSL_PARAM_BLD_push_BN)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn add_bn(&mut self, key: &CStr, bn: &BigNumRef) -> Result<(), ErrorStack> { | ||
unsafe { | ||
cvt(ffi::OSSL_PARAM_BLD_push_BN( | ||
self.as_ptr(), | ||
key.as_ptr(), | ||
bn.as_ptr(), | ||
)) | ||
.map(|_| ()) | ||
} | ||
} | ||
|
||
/// Adds a utf8 string to `OsslParamBuilder`. | ||
/// | ||
/// Note, that both `key` and `buf` need to exist until the `to_param` is called! | ||
#[corresponds(OSSL_PARAM_BLD_push_utf8_string)] | ||
#[allow(dead_code)] // TODO: remove when when used by ML-DSA / ML-KEM | ||
pub(crate) fn add_utf8_string(&mut self, key: &CStr, buf: &str) -> Result<(), ErrorStack> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to tie the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, it's even there in the comment. I'll tie them all together. |
||
unsafe { | ||
cvt(ffi::OSSL_PARAM_BLD_push_utf8_string( | ||
self.as_ptr(), | ||
key.as_ptr(), | ||
buf.as_ptr() as *const c_char, | ||
buf.len(), | ||
)) | ||
.map(|_| ()) | ||
} | ||
} | ||
|
||
/// Adds a octet string to `OsslParamBuilder`. | ||
/// | ||
/// Note, that both `key` and `buf` need to exist until the `to_param` is called! | ||
#[corresponds(OSSL_PARAM_BLD_push_octet_string)] | ||
#[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] | ||
pub(crate) fn add_octet_string(&mut self, key: &CStr, buf: &[u8]) -> Result<(), ErrorStack> { | ||
unsafe { | ||
cvt(ffi::OSSL_PARAM_BLD_push_octet_string( | ||
self.as_ptr(), | ||
key.as_ptr(), | ||
buf.as_ptr() as *const c_void, | ||
buf.len(), | ||
)) | ||
.map(|_| ()) | ||
} | ||
} | ||
|
||
/// Adds a unsigned int to `OsslParamBuilder`. | ||
/// | ||
/// Note, that both `key` and `buf` need to exist until the `to_param` is called! | ||
#[corresponds(OSSL_PARAM_BLD_push_uint)] | ||
#[cfg_attr(any(not(ossl320), osslconf = "OPENSSL_NO_ARGON2"), allow(dead_code))] | ||
pub(crate) fn add_uint(&mut self, key: &CStr, val: u32) -> Result<(), ErrorStack> { | ||
unsafe { | ||
cvt(ffi::OSSL_PARAM_BLD_push_uint( | ||
self.as_ptr(), | ||
key.as_ptr(), | ||
val as c_uint, | ||
)) | ||
.map(|_| ()) | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.