From 8ce5dee00d1f7658e0790b60dfcb86d4b2f81621 Mon Sep 17 00:00:00 2001 From: Umang Raghuvanshi Date: Fri, 20 Apr 2018 17:15:04 +0530 Subject: [PATCH] Add the CMS_sign and i2d_CMS_ContentInfo function bindings This adds the CMS_sign and i2d_CMS_ContentInfo bindings in the openssl-sys crate and Rusty wrappers in the openssl crate. --- openssl-sys/src/lib.rs | 12 +++++++++- openssl/src/cms.rs | 50 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 85527f8f..42bd8268 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -5,8 +5,8 @@ extern crate libc; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t, FILE}; -use std::ptr; use std::mem; +use std::ptr; #[cfg(any(ossl101, ossl102))] mod ossl10x; @@ -2846,6 +2846,16 @@ extern "C" { pub fn SMIME_read_CMS(bio: *mut BIO, bcont: *mut *mut BIO) -> *mut CMS_ContentInfo; #[cfg(not(libressl))] pub fn CMS_ContentInfo_free(cms: *mut CMS_ContentInfo); + #[cfg(not(libressl))] + pub fn CMS_sign( + signcert: *const X509, + pkey: *const EVP_PKEY, + certs: *const stack_st_X509, + data: *mut BIO, + flags: c_uint, + ) -> *mut CMS_ContentInfo; + #[cfg(not(libressl))] + pub fn i2d_CMS_ContentInfo(a: *mut CMS_ContentInfo, pp: *mut *mut c_uchar) -> c_int; #[cfg(not(libressl))] pub fn FIPS_mode_set(onoff: c_int) -> c_int; diff --git a/openssl/src/cms.rs b/openssl/src/cms.rs index 8c60455c..b549e066 100644 --- a/openssl/src/cms.rs +++ b/openssl/src/cms.rs @@ -9,11 +9,12 @@ use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; use std::ptr; -use {cvt, cvt_p}; use bio::{MemBio, MemBioSlice}; use error::ErrorStack; use pkey::{HasPrivate, PKeyRef}; +use stack::Stack; use x509::X509; +use {cvt, cvt_p}; foreign_type_and_impl_send_sync! { type CType = ffi::CMS_ContentInfo; @@ -80,4 +81,51 @@ impl CmsContentInfo { Ok(CmsContentInfo::from_ptr(cms)) } } + + /// Given a signing cert `signcert`, private key `pkey`, an optional certificate stack `certs`, + /// data `data` and flags `flags`, create a CmsContentInfo struct. + /// + /// OpenSSL documentation at [`CMS_sign`] + /// + /// [`CMS_sign`]: https://www.openssl.org/docs/manmaster/man3/CMS_sign.html + pub fn sign( + signcert: &X509, + pkey: &PKeyRef, + certs: Option<&Stack>, + data: &[u8], + flags: u32, + ) -> Result { + unsafe { + let signcert = signcert.as_ptr(); + let pkey = pkey.as_ptr(); + let data_bio = MemBioSlice::new(data)?; + let cms = cvt_p(ffi::CMS_sign( + signcert, + pkey, + certs.unwrap_or(&Stack::::new()?).as_ptr(), + data_bio.as_ptr(), + flags, + ))?; + + Ok(CmsContentInfo::from_ptr(cms)) + } + } + + /// Serializes this CmsContentInfo using DER. + /// + /// OpenSSL documentation at [`i2d_CMS_ContentInfo`] + /// + /// [`i2d_CMS_ContentInfo`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_CMS_ContentInfo.html + pub fn to_der(&mut self) -> Result, ErrorStack> { + unsafe { + let size = ffi::i2d_CMS_ContentInfo(self.as_ptr(), ptr::null_mut()); + let mut der = vec![0u8; size as usize]; + + let raw_ptr = Box::into_raw(Box::new(der.as_mut_ptr())); + ffi::i2d_CMS_ContentInfo(self.as_ptr(), raw_ptr); + + Box::from_raw(raw_ptr); + Ok(der) + } + } }