diff options
| author | Steven Fackler <[email protected]> | 2018-03-19 13:22:51 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2018-03-19 13:22:51 -0700 |
| commit | 063186b62eb06ce77f96fb22b624f4943b360d81 (patch) | |
| tree | ed0d682b2ab4571293fd6aa64877a8877abdc217 /openssl/src | |
| parent | Merge pull request #879 from sfackler/no-features (diff) | |
| parent | Make it possible to use cmac (diff) | |
| download | rust-openssl-063186b62eb06ce77f96fb22b624f4943b360d81.tar.xz rust-openssl-063186b62eb06ce77f96fb22b624f4943b360d81.zip | |
Merge pull request #856 from Flakebi/master
Make it possible to use cmac
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/pkey.rs | 62 | ||||
| -rw-r--r-- | openssl/src/sign.rs | 37 |
2 files changed, 98 insertions, 1 deletions
diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 66ff33d6..322e6416 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -365,6 +365,68 @@ impl PKey<Private> { } } + /// Creates a new `PKey` containing a CMAC key. + /// + /// CMAC is only supported since the version 1.1.0 of OpenSSL. + /// + /// # Note + /// + /// To compute CMAC values, use the `sign` module. + #[cfg(any(all(ossl110, feature = "v110"), all(ossl111, feature = "v111")))] + pub fn cmac(cipher: &::symm::Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> { + unsafe { + assert!(key.len() <= c_int::max_value() as usize); + let kctx = cvt_p(ffi::EVP_PKEY_CTX_new_id( + ffi::EVP_PKEY_CMAC, + ptr::null_mut(), + ))?; + + let ret = (|| { + cvt(ffi::EVP_PKEY_keygen_init(kctx))?; + + // Set cipher for cmac + cvt(ffi::EVP_PKEY_CTX_ctrl( + kctx, + -1, + ffi::EVP_PKEY_OP_KEYGEN, + ffi::EVP_PKEY_CTRL_CIPHER, + 0, + cipher.as_ptr() as *mut _, + ))?; + + // Set the key data + cvt(ffi::EVP_PKEY_CTX_ctrl( + kctx, + -1, + ffi::EVP_PKEY_OP_KEYGEN, + ffi::EVP_PKEY_CTRL_SET_MAC_KEY, + key.len() as c_int, + key.as_ptr() as *mut _, + ))?; + Ok(()) + })(); + + if let Err(e) = ret { + // Free memory + ffi::EVP_PKEY_CTX_free(kctx); + return Err(e); + } + + // Generate key + let mut key = ptr::null_mut(); + let ret = cvt(ffi::EVP_PKEY_keygen(kctx, &mut key)); + + // Free memory + ffi::EVP_PKEY_CTX_free(kctx); + + if let Err(e) = ret { + return Err(e); + } + + Ok(PKey::from_ptr(key)) + } + } + private_key_from_pem! { /// Deserializes a private key from a PEM-encoded key type specific format. /// diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index 6a49cb49..9270d222 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -130,6 +130,26 @@ impl<'a> Signer<'a> { where T: HasPrivate, { + Self::new_intern(Some(type_), pkey) + } + + /// Creates a new `Signer` without a digest. + /// + /// This can be used to create a CMAC. + /// OpenSSL documentation at [`EVP_DigestSignInit`]. + /// + /// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html + pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> + where + T: HasPrivate, + { + Self::new_intern(None, pkey) + } + + pub fn new_intern<T>(type_: Option<MessageDigest>, pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> + where + T: HasPrivate, + { unsafe { ffi::init(); @@ -138,7 +158,7 @@ impl<'a> Signer<'a> { let r = ffi::EVP_DigestSignInit( ctx, &mut pctx, - type_.as_ptr(), + type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()), ptr::null_mut(), pkey.as_ptr(), ); @@ -638,6 +658,21 @@ mod test { test_hmac(MessageDigest::sha1(), &tests); } + #[cfg(ossl110)] + #[test] + fn test_cmac() { + let cipher = ::symm::Cipher::aes_128_cbc(); + let key = Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap(); + let pkey = PKey::cmac(&cipher, &key).unwrap(); + let mut signer = Signer::new_without_digest(&pkey).unwrap(); + + let data = b"Hi There"; + signer.update(data as &[u8]).unwrap(); + + let expected = vec![136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19]; + assert_eq!(signer.sign_to_vec().unwrap(), expected); + } + #[test] fn ec() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); |