Unverified Commit 53671518 authored by Steven Fackler's avatar Steven Fackler Committed by GitHub
Browse files

Merge pull request #902 from ur0/CMS_sign

Add the CMS_sign and i2d_CMS_ContentInfo function bindings
parents 5debc1ba afaa2387
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -1465,6 +1465,51 @@ pub const GEN_RID: c_int = 8;

pub const DTLS1_COOKIE_LENGTH: c_uint = 256;

#[cfg(not(libressl))]
pub const CMS_TEXT: c_uint = 0x1;
#[cfg(not(libressl))]
pub const CMS_NOCERTS: c_uint = 0x2;
#[cfg(not(libressl))]
pub const CMS_NO_CONTENT_VERIFY: c_uint = 0x4;
#[cfg(not(libressl))]
pub const CMS_NO_ATTR_VERIFY: c_uint = 0x8;
#[cfg(not(libressl))]
pub const CMS_NOSIGS: c_uint = 0x4 | 0x8;
#[cfg(not(libressl))]
pub const CMS_NOINTERN: c_uint = 0x10;
#[cfg(not(libressl))]
pub const CMS_NO_SIGNER_CERT_VERIFY: c_uint = 0x20;
#[cfg(not(libressl))]
pub const CMS_NOVERIFY: c_uint = 0x20;
#[cfg(not(libressl))]
pub const CMS_DETACHED: c_uint = 0x40;
#[cfg(not(libressl))]
pub const CMS_BINARY: c_uint = 0x80;
#[cfg(not(libressl))]
pub const CMS_NOATTR: c_uint = 0x100;
#[cfg(not(libressl))]
pub const CMS_NOSMIMECAP: c_uint = 0x200;
#[cfg(not(libressl))]
pub const CMS_NOOLDMIMETYPE: c_uint = 0x400;
#[cfg(not(libressl))]
pub const CMS_CRLFEOL: c_uint = 0x800;
#[cfg(not(libressl))]
pub const CMS_STREAM: c_uint = 0x1000;
#[cfg(not(libressl))]
pub const CMS_NOCRL: c_uint = 0x2000;
#[cfg(not(libressl))]
pub const CMS_PARTIAL: c_uint = 0x4000;
#[cfg(not(libressl))]
pub const CMS_REUSE_DIGEST: c_uint = 0x8000;
#[cfg(not(libressl))]
pub const CMS_USE_KEYID: c_uint = 0x10000;
#[cfg(not(libressl))]
pub const CMS_DEBUG_DECRYPT: c_uint = 0x20000;
#[cfg(all(not(libressl), not(ossl101)))]
pub const CMS_KEY_PARAM: c_uint = 0x40000;
#[cfg(all(not(libressl), not(ossl101), not(ossl102)))]
pub const CMS_ASCIICRLF: c_uint = 0x80000;

// macros
pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long {
    BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void)
@@ -2856,6 +2901,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: *mut X509,
        pkey: *mut EVP_PKEY,
        certs: *mut 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;
+87 −1
Original line number Diff line number Diff line
@@ -9,11 +9,42 @@ use ffi;
use foreign_types::{ForeignType, ForeignTypeRef};
use std::ptr;

use {cvt, cvt_p};
use bio::{MemBio, MemBioSlice};
use error::ErrorStack;
use libc::c_uint;
use pkey::{HasPrivate, PKeyRef};
use stack::Stack;
use x509::X509;
use {cvt, cvt_p};

bitflags! {
    pub struct CMSOptions : c_uint {
        const TEXT = ffi::CMS_TEXT;
        const CMS_NOCERTS = ffi::CMS_NOCERTS;
        const NO_CONTENT_VERIFY = ffi::CMS_NO_CONTENT_VERIFY;
        const NO_ATTR_VERIFY = ffi::CMS_NO_ATTR_VERIFY;
        const NOSIGS = ffi::CMS_NOSIGS;
        const NOINTERN = ffi::CMS_NOINTERN;
        const NO_SIGNER_CERT_VERIFY = ffi::CMS_NO_SIGNER_CERT_VERIFY;
        const NOVERIFY = ffi::CMS_NOVERIFY;
        const DETACHED = ffi::CMS_DETACHED;
        const BINARY = ffi::CMS_BINARY;
        const NOATTR = ffi::CMS_NOATTR;
        const NOSMIMECAP = ffi::CMS_NOSMIMECAP;
        const NOOLDMIMETYPE = ffi::CMS_NOOLDMIMETYPE;
        const CRLFEOL = ffi::CMS_CRLFEOL;
        const STREAM = ffi::CMS_STREAM;
        const NOCRL = ffi::CMS_NOCRL;
        const PARTIAL = ffi::CMS_PARTIAL;
        const REUSE_DIGEST = ffi::CMS_REUSE_DIGEST;
        const USE_KEYID = ffi::CMS_USE_KEYID;
        const DEBUG_DECRYPT = ffi::CMS_DEBUG_DECRYPT;
        #[cfg(all(not(libressl), not(ossl101)))]
        const KEY_PARAM = ffi::CMS_KEY_PARAM;
        #[cfg(all(not(libressl), not(ossl101), not(ossl102)))]
        const ASCIICRLF = ffi::CMS_ASCIICRLF;
    }
}

foreign_type_and_impl_send_sync! {
    type CType = ffi::CMS_ContentInfo;
@@ -63,6 +94,16 @@ impl CmsContentInfoRef {
            Ok(out.get_buf().to_owned())
        }
    }

    to_der! {
    /// 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
    to_der,
    ffi::i2d_CMS_ContentInfo
    }
}

impl CmsContentInfo {
@@ -80,4 +121,49 @@ impl CmsContentInfo {
            Ok(CmsContentInfo::from_ptr(cms))
        }
    }

    /// Given a signing cert `signcert`, private key `pkey`, a certificate stack `certs`,
    /// data `data` and flags `flags`, create a CmsContentInfo struct.
    ///
    /// All arguments are optional.
    ///
    /// OpenSSL documentation at [`CMS_sign`]
    ///
    /// [`CMS_sign`]: https://www.openssl.org/docs/manmaster/man3/CMS_sign.html
    pub fn sign<T: HasPrivate>(
        signcert: Option<&X509>,
        pkey: Option<&PKeyRef<T>>,
        certs: Option<&Stack<X509>>,
        data: Option<&[u8]>,
        flags: CMSOptions,
    ) -> Result<CmsContentInfo, ErrorStack> {
        unsafe {
            let signcert = match signcert {
                Some(cert) => cert.as_ptr(),
                None => ptr::null_mut(),
            };
            let pkey = match pkey {
                Some(pkey) => pkey.as_ptr(),
                None => ptr::null_mut(),
            };
            let data_bio_ptr = match data {
                Some(data) => MemBioSlice::new(data)?.as_ptr(),
                None => ptr::null_mut(),
            };
            let certs = match certs {
                Some(certs) => certs.as_ptr(),
                None => ptr::null_mut(),
            };

            let cms = cvt_p(ffi::CMS_sign(
                signcert,
                pkey,
                certs,
                data_bio_ptr,
                flags.bits(),
            ))?;

            Ok(CmsContentInfo::from_ptr(cms))
        }
    }
}