Skip to content

Commit d26c91b

Browse files
committed
Expose encapsulation and decapsulation.
1 parent 7ceae78 commit d26c91b

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

openssl-sys/src/handwritten/evp.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,34 @@ extern "C" {
649649
sig: *const c_uchar,
650650
siglen: size_t,
651651
) -> c_int;
652+
653+
#[cfg(ossl300)]
654+
pub fn EVP_PKEY_encapsulate_init(
655+
ctx: *mut EVP_PKEY_CTX,
656+
params: *const OSSL_PARAM,
657+
) -> c_int;
658+
#[cfg(ossl300)]
659+
pub fn EVP_PKEY_encapsulate(
660+
ctx: *mut EVP_PKEY_CTX,
661+
wrappedkey: *mut c_uchar,
662+
wrappedkeylen: *mut size_t,
663+
genkey: *mut c_uchar,
664+
genkeylen: *mut size_t,
665+
) -> c_int;
666+
667+
#[cfg(ossl300)]
668+
pub fn EVP_PKEY_decapsulate_init(
669+
ctx: *mut EVP_PKEY_CTX,
670+
params: *const OSSL_PARAM,
671+
) -> c_int;
672+
#[cfg(ossl300)]
673+
pub fn EVP_PKEY_decapsulate(
674+
ctx: *mut EVP_PKEY_CTX,
675+
genkey: *mut c_uchar,
676+
genkeylen: *mut size_t,
677+
wrappedkey: *const c_uchar,
678+
wrappedkeylen: size_t,
679+
) -> c_int;
652680
}
653681

654682
const_ptr_api! {

openssl/src/pkey_ctx.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,18 @@ where
197197
Ok(())
198198
}
199199

200+
/// Prepares the context for encapsulateion using the public key.
201+
#[corresponds(EVP_PKEY_encapsulate_init)]
202+
#[inline]
203+
pub fn encapsulate_init(&mut self) -> Result<(), ErrorStack> {
204+
unsafe {
205+
cvt(ffi::EVP_PKEY_encapsulate_init(self.as_ptr(),
206+
ptr::null()))?;
207+
}
208+
209+
Ok(())
210+
}
211+
200212
/// Prepares the context for signature verification using the public key.
201213
#[corresponds(EVP_PKEY_verify_init)]
202214
#[inline]
@@ -250,6 +262,43 @@ where
250262
Ok(len)
251263
}
252264

265+
/// Performs a public key encapsulation operation.
266+
#[corresponds(EVP_PKEY_encapsulate)]
267+
pub fn encapsulate(&mut self, wrappedkey: Option<&mut [u8]>, genkey: Option<&mut [u8]>)
268+
-> Result<(usize, usize), ErrorStack>
269+
{
270+
let mut wrappedkey_len = wrappedkey.as_ref().map_or(0, |b| b.len());
271+
let mut genkey_len = genkey.as_ref().map_or(0, |b| b.len());
272+
unsafe {
273+
cvt(ffi::EVP_PKEY_encapsulate(
274+
self.as_ptr(),
275+
wrappedkey.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
276+
&mut wrappedkey_len,
277+
genkey.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
278+
&mut genkey_len,
279+
))?;
280+
}
281+
282+
Ok((wrappedkey_len, genkey_len))
283+
}
284+
285+
/// Like [`Self::encapsulate`] but appends ciphertext and key to a [`Vec`].
286+
pub fn encapsulate_to_vec(&mut self, wrappedkey: &mut Vec<u8>, genkey: &mut Vec<u8>)
287+
-> Result<(usize, usize), ErrorStack>
288+
{
289+
let wrappedkey_base = wrappedkey.len();
290+
let genkey_base = genkey.len();
291+
let (wrappedkey_len, genkey_len) = self.encapsulate(None, None)?;
292+
wrappedkey.resize(wrappedkey_base + wrappedkey_len, 0);
293+
genkey.resize(genkey_base + genkey_len, 0);
294+
let (wrappedkey_len, genkey_len) =
295+
self.encapsulate(Some(&mut wrappedkey[wrappedkey_base..]),
296+
Some(&mut genkey[genkey_base..]))?;
297+
wrappedkey.truncate(wrappedkey_base + wrappedkey_len);
298+
genkey.truncate(genkey_base + genkey_len);
299+
Ok((wrappedkey_len, genkey_len))
300+
}
301+
253302
/// Verifies the signature of data using the public key.
254303
///
255304
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
@@ -329,6 +378,17 @@ where
329378
Ok(())
330379
}
331380

381+
/// Prepares the context for decapsulation using the private key.
382+
#[corresponds(EVP_PKEY_decapsulate_init)]
383+
#[inline]
384+
pub fn decapsulate_init(&mut self) -> Result<(), ErrorStack> {
385+
unsafe {
386+
cvt(ffi::EVP_PKEY_decapsulate_init(self.as_ptr(), ptr::null()))?;
387+
}
388+
389+
Ok(())
390+
}
391+
332392
/// Prepares the context for signing using the private key.
333393
#[corresponds(EVP_PKEY_sign_init)]
334394
#[inline]
@@ -384,6 +444,37 @@ where
384444
Ok(len)
385445
}
386446

447+
/// Performs a decapsulation operation using the private key.
448+
#[corresponds(EVP_PKEY_decapsulate)]
449+
pub fn decapsulate(&mut self, from: &[u8], to: Option<&mut [u8]>)
450+
-> Result<usize, ErrorStack>
451+
{
452+
let mut written = to.as_ref().map_or(0, |b| b.len());
453+
unsafe {
454+
cvt(ffi::EVP_PKEY_decapsulate(
455+
self.as_ptr(),
456+
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
457+
&mut written,
458+
from.as_ptr(),
459+
from.len(),
460+
))?;
461+
}
462+
463+
Ok(written)
464+
}
465+
466+
/// Like [`Self::decapsulate`] but appends plaintext to a [`Vec`].
467+
pub fn decapsulate_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>)
468+
-> Result<usize, ErrorStack>
469+
{
470+
let base = out.len();
471+
let len = self.decapsulate(from, None)?;
472+
out.resize(base + len, 0);
473+
let len = self.decapsulate(from, Some(&mut out[base..]))?;
474+
out.truncate(base + len);
475+
Ok(len)
476+
}
477+
387478
/// Signs the contents of `data`.
388479
///
389480
/// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be

0 commit comments

Comments
 (0)