Skip to content

Commit cd8b1da

Browse files
committed
add internal wrapper around OSSL_PARAM array
1 parent e580012 commit cd8b1da

File tree

1 file changed

+178
-36
lines changed

1 file changed

+178
-36
lines changed

openssl/src/params.rs

Lines changed: 178 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,115 @@
11
use crate::bn::BigNumRef;
22
use crate::error::ErrorStack;
33
use crate::{cvt, cvt_p};
4-
use foreign_types::ForeignType;
4+
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
55
use libc::{c_char, c_void};
66
use openssl_macros::corresponds;
77
use std::ffi::CStr;
88
use std::marker::PhantomData;
99

10+
pub struct Params<'a>(*mut ffi::OSSL_PARAM, PhantomData<&'a ()>);
11+
12+
impl<'a> ForeignType for Params<'a> {
13+
type CType = ffi::OSSL_PARAM;
14+
type Ref = ParamsRef<'a>;
15+
16+
#[inline]
17+
unsafe fn from_ptr(ptr: *mut ffi::OSSL_PARAM) -> Params<'a> {
18+
Self(ptr, PhantomData)
19+
}
20+
21+
#[inline]
22+
fn as_ptr(&self) -> *mut ffi::OSSL_PARAM {
23+
self.0
24+
}
25+
}
26+
27+
impl Drop for Params<'_> {
28+
fn drop(&mut self) {
29+
unsafe { ffi::OSSL_PARAM_free(self.0) };
30+
}
31+
}
32+
33+
impl Clone for Params<'_> {
34+
#[inline]
35+
fn clone(&self) -> Self {
36+
Self(unsafe { ffi::OSSL_PARAM_dup(self.0) }, PhantomData)
37+
}
38+
}
39+
40+
impl<'a> ToOwned for ParamsRef<'a> {
41+
type Owned = Params<'a>;
42+
43+
#[inline]
44+
fn to_owned(&self) -> Params<'a> {
45+
unsafe {
46+
let handle: *mut ffi::OSSL_PARAM = ffi::OSSL_PARAM_dup(self.as_ptr());
47+
ForeignType::from_ptr(handle)
48+
}
49+
}
50+
}
51+
52+
impl<'a> std::ops::Deref for Params<'a> {
53+
type Target = ParamsRef<'a>;
54+
55+
#[inline]
56+
fn deref(&self) -> &ParamsRef<'a> {
57+
unsafe { ParamsRef::from_ptr(self.as_ptr()) }
58+
}
59+
}
60+
61+
impl<'a> std::ops::DerefMut for Params<'a> {
62+
#[inline]
63+
fn deref_mut(&mut self) -> &mut ParamsRef<'a> {
64+
unsafe { ParamsRef::from_ptr_mut(self.as_ptr()) }
65+
}
66+
}
67+
68+
impl<'a> std::borrow::Borrow<ParamsRef<'a>> for Params<'a> {
69+
#[inline]
70+
fn borrow(&self) -> &ParamsRef<'a> {
71+
self
72+
}
73+
}
74+
75+
impl<'a> AsRef<ParamsRef<'a>> for Params<'a> {
76+
#[inline]
77+
fn as_ref(&self) -> &ParamsRef<'a> {
78+
self
79+
}
80+
}
81+
82+
pub struct ParamsRef<'a>(Opaque, PhantomData<&'a ()>);
83+
84+
impl ForeignTypeRef for ParamsRef<'_> {
85+
type CType = ffi::OSSL_PARAM;
86+
}
87+
88+
unsafe impl Send for Params<'_> {}
89+
unsafe impl Send for ParamsRef<'_> {}
90+
unsafe impl Sync for Params<'_> {}
91+
unsafe impl Sync for ParamsRef<'_> {}
92+
93+
impl<'a> ParamsRef<'a> {
94+
/// Merges two `ParamsRef` objects into a new `Params` object.
95+
#[corresponds(OSSL_PARAM_merge)]
96+
pub fn merge(&self, other: &ParamsRef<'a>) -> Result<Params<'a>, ErrorStack> {
97+
cvt_p(unsafe { ffi::OSSL_PARAM_merge(self.as_ptr(), other.as_ptr()) })
98+
.map(|p| unsafe { Params::from_ptr(p) })
99+
}
100+
101+
/// Locate a parameter by the given key.
102+
#[corresponds(OSSL_PARAM_locate_const)]
103+
fn locate(&self, key: &CStr) -> Option<*const ffi::OSSL_PARAM> {
104+
let param = unsafe { ffi::OSSL_PARAM_locate_const(self.as_ptr(), key.as_ptr()) };
105+
if param.is_null() {
106+
None
107+
} else {
108+
Some(param)
109+
}
110+
}
111+
}
112+
10113
pub struct ParamBuilder<'a>(*mut ffi::OSSL_PARAM_BLD, PhantomData<&'a ()>);
11114

12115
impl Drop for ParamBuilder<'_> {
@@ -28,13 +131,14 @@ impl<'a, 'b> ParamBuilder<'a> {
28131

29132
/// Push a BigNum parameter into the builder.
30133
#[corresponds[OSSL_PARAM_BLD_push_BN]]
31-
pub fn push_bignum(&mut self, key: &'b CStr, bn: &'a BigNumRef) -> Result<(), ErrorStack> {
32-
cvt(unsafe { ffi::OSSL_PARAM_BLD_push_BN(self.0, key.as_ptr(), bn.as_ptr()) }).map(|_| ())
134+
pub fn push_bignum(self, key: &'b CStr, bn: &'a BigNumRef) -> Result<Self, ErrorStack> {
135+
cvt(unsafe { ffi::OSSL_PARAM_BLD_push_BN(self.0, key.as_ptr(), bn.as_ptr()) })?;
136+
Ok(self)
33137
}
34138

35139
/// Push a UTF-8 String parameter into the builder.
36140
#[corresponds[OSSL_PARAM_BLD_push_utf8_string]]
37-
pub fn push_utf_string(&mut self, key: &'b CStr, string: &'a str) -> Result<(), ErrorStack> {
141+
pub fn push_utf_string(self, key: &'b CStr, string: &'a str) -> Result<Self, ErrorStack> {
38142
let value = string.as_bytes();
39143
cvt(unsafe {
40144
ffi::OSSL_PARAM_BLD_push_utf8_string(
@@ -43,8 +147,8 @@ impl<'a, 'b> ParamBuilder<'a> {
43147
value.as_ptr().cast::<c_char>(),
44148
value.len(),
45149
)
46-
})
47-
.map(|_| ())
150+
})?;
151+
Ok(self)
48152
}
49153

50154
/// Push a byte string parameter into the builder.
@@ -80,8 +184,9 @@ impl<'a, 'b> ParamBuilder<'a> {
80184

81185
/// Build a `Params` array from the builder consuming the builder.
82186
#[corresponds(OSSL_PARAM_BLD_to_param)]
83-
pub fn build(self) -> Result<*mut ffi::OSSL_PARAM, ErrorStack> {
84-
cvt_p(unsafe { ffi::OSSL_PARAM_BLD_to_param(self.0) })
187+
pub fn build(self) -> Result<Params<'b>, ErrorStack> {
188+
let ptr = cvt_p(unsafe { ffi::OSSL_PARAM_BLD_to_param(self.0) })?;
189+
Ok(unsafe { Params::from_ptr(ptr) })
85190
}
86191
}
87192

@@ -91,12 +196,10 @@ mod test {
91196
use crate::bn::BigNum;
92197
use crate::util::c_str;
93198

94-
fn assert_param(params: *mut ffi::OSSL_PARAM, key: &CStr, is_null: bool) {
95-
let param = unsafe { ffi::OSSL_PARAM_locate_const(params, key.as_ptr()) };
96-
if is_null {
97-
assert!(param.is_null(), "Unexpectedly found param: {key:?}");
98-
} else {
99-
assert!(!param.is_null(), "Failed to find param: {key:?}");
199+
fn assert_param(params: &ParamsRef<'_>, key: &CStr, is_null: bool) {
200+
match params.locate(key) {
201+
Some(_) => assert!(!is_null, "Unexpectedly found param: {key:?}"),
202+
None => assert!(is_null, "Failed to find param: {key:?}"),
100203
}
101204
}
102205

@@ -108,8 +211,8 @@ mod test {
108211
.build()
109212
.unwrap();
110213

111-
assert_param(params, c_str(b"nonce-type\0"), false);
112-
assert_param(params, c_str(b"group\0"), true);
214+
assert_param(&params, c_str(b"nonce-type\0"), false);
215+
assert_param(&params, c_str(b"group\0"), true);
113216
}
114217

115218
#[test]
@@ -120,39 +223,43 @@ mod test {
120223
.build()
121224
.unwrap();
122225

123-
assert_param(params, c_str(b"size\0"), false);
124-
assert_param(params, c_str(b"out\0"), true);
226+
assert_param(&params, c_str(b"size\0"), false);
227+
assert_param(&params, c_str(b"out\0"), true);
125228
}
126229

127230
#[test]
128231
fn test_param_builder_bignum() {
129-
let n = BigNum::from_u32(0xbc747fc5).unwrap();
130-
let e = BigNum::from_u32(0x10001).unwrap();
131-
let d = BigNum::from_u32(0x7b133399).unwrap();
232+
let a = BigNum::from_u32(0x01).unwrap();
233+
let b = BigNum::from_u32(0x02).unwrap();
234+
let c = BigNum::from_u32(0x03).unwrap();
132235

133-
let mut builder = ParamBuilder::new();
134-
builder.push_bignum(c_str(b"n\0"), &n).unwrap();
135-
builder.push_bignum(c_str(b"e\0"), &e).unwrap();
136-
builder.push_bignum(c_str(b"d\0"), &d).unwrap();
137-
let params = builder.build().unwrap();
236+
let params = ParamBuilder::new()
237+
.push_bignum(c_str(b"a\0"), &a)
238+
.unwrap()
239+
.push_bignum(c_str(b"b\0"), &b)
240+
.unwrap()
241+
.push_bignum(c_str(b"c\0"), &c)
242+
.unwrap()
243+
.build()
244+
.unwrap();
138245

139-
for param in [b"n\0", b"e\0", b"d\0"] {
140-
assert_param(params, c_str(param), false);
246+
for param in [b"a\0", b"e\0", b"c\0"] {
247+
assert_param(&params, c_str(param), false);
141248
}
142249

143-
assert_param(params, c_str(b"group\0"), true);
250+
assert_param(&params, c_str(b"group\0"), true);
144251
}
145252

146253
#[test]
147254
fn test_param_builder_string() {
148-
let mut builder = ParamBuilder::new();
149-
builder
255+
let params = ParamBuilder::new()
150256
.push_utf_string(c_str(b"group\0"), "primve256v1")
257+
.unwrap()
258+
.build()
151259
.unwrap();
152-
let params = builder.build().unwrap();
153260

154-
assert_param(params, c_str(b"group\0"), false);
155-
assert_param(params, c_str(b"n\0"), true);
261+
assert_param(&params, c_str(b"group\0"), false);
262+
assert_param(&params, c_str(b"n\0"), true);
156263
}
157264

158265
#[test]
@@ -163,7 +270,42 @@ mod test {
163270
.build()
164271
.unwrap();
165272

166-
assert_param(params, c_str(b"pass\0"), false);
167-
assert_param(params, c_str(b"group\0"), true);
273+
assert_param(&params, c_str(b"pass\0"), false);
274+
assert_param(&params, c_str(b"group\0"), true);
275+
}
276+
277+
#[test]
278+
fn test_merge() {
279+
let n = BigNum::from_u32(0xbc747fc5).unwrap();
280+
let e = BigNum::from_u32(0x10001).unwrap();
281+
let d = BigNum::from_u32(0x7b133399).unwrap();
282+
283+
let params1 = ParamBuilder::new()
284+
.push_bignum(c_str(b"n\0"), &n)
285+
.unwrap()
286+
.build()
287+
.unwrap();
288+
let params2 = ParamBuilder::new()
289+
.push_bignum(c_str(b"e\0"), &e)
290+
.unwrap()
291+
.build()
292+
.unwrap();
293+
let params3 = ParamBuilder::new()
294+
.push_bignum(c_str(b"d\0"), &d)
295+
.unwrap()
296+
.build()
297+
.unwrap();
298+
299+
// Merge 1 & 2, d (added in 3) should not be present
300+
let merged_params = params1.merge(&params2).unwrap();
301+
assert_param(&merged_params, c_str(b"n\0"), false);
302+
assert_param(&merged_params, c_str(b"e\0"), false);
303+
assert_param(&merged_params, c_str(b"d\0"), true);
304+
305+
// Merge 3 into 1+2, we should now have all params
306+
let merged_params = merged_params.merge(&params3).unwrap();
307+
assert_param(&merged_params, c_str(b"n\0"), false);
308+
assert_param(&merged_params, c_str(b"e\0"), false);
309+
assert_param(&merged_params, c_str(b"e\0"), false);
168310
}
169311
}

0 commit comments

Comments
 (0)