Migrate DSA sign/verify to EVP APIs
This commit is contained in:
parent
228b8fbc5b
commit
6609a81685
|
|
@ -110,6 +110,7 @@ pub const CRYPTO_LOCK: c_int = 1;
|
||||||
pub const EVP_MAX_MD_SIZE: c_uint = 64;
|
pub const EVP_MAX_MD_SIZE: c_uint = 64;
|
||||||
pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption;
|
pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption;
|
||||||
pub const EVP_PKEY_HMAC: c_int = NID_hmac;
|
pub const EVP_PKEY_HMAC: c_int = NID_hmac;
|
||||||
|
pub const EVP_PKEY_DSA: c_int = NID_dsa;
|
||||||
|
|
||||||
pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1;
|
pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1;
|
||||||
pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2;
|
pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2;
|
||||||
|
|
@ -120,6 +121,7 @@ pub const MBSTRING_UTF8: c_int = MBSTRING_FLAG;
|
||||||
pub const NID_rsaEncryption: c_int = 6;
|
pub const NID_rsaEncryption: c_int = 6;
|
||||||
pub const NID_ext_key_usage: c_int = 126;
|
pub const NID_ext_key_usage: c_int = 126;
|
||||||
pub const NID_key_usage: c_int = 83;
|
pub const NID_key_usage: c_int = 83;
|
||||||
|
pub const NID_dsa: c_int = 116;
|
||||||
pub const NID_hmac: c_int = 855;
|
pub const NID_hmac: c_int = 855;
|
||||||
|
|
||||||
pub const PKCS5_SALT_LEN: c_int = 8;
|
pub const PKCS5_SALT_LEN: c_int = 8;
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,14 @@ use ffi;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use libc::{c_uint, c_int, c_char, c_void};
|
use libc::{c_int, c_char, c_void};
|
||||||
|
|
||||||
use bn::BigNumRef;
|
use bn::BigNumRef;
|
||||||
use bio::{MemBio, MemBioSlice};
|
use bio::{MemBio, MemBioSlice};
|
||||||
use crypto::hash;
|
|
||||||
use HashTypeInternals;
|
|
||||||
use crypto::util::{CallbackState, invoke_passwd_cb};
|
use crypto::util::{CallbackState, invoke_passwd_cb};
|
||||||
|
|
||||||
|
|
||||||
/// Builder for upfront DSA parameter generateration
|
/// Builder for upfront DSA parameter generation
|
||||||
pub struct DSAParams(*mut ffi::DSA);
|
pub struct DSAParams(*mut ffi::DSA);
|
||||||
|
|
||||||
impl DSAParams {
|
impl DSAParams {
|
||||||
|
|
@ -156,39 +154,6 @@ impl DSA {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
let k_len = self.size().expect("DSA missing a q") as c_uint;
|
|
||||||
let mut sig = vec![0; k_len as usize];
|
|
||||||
let mut sig_len = k_len;
|
|
||||||
assert!(self.has_private_key());
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
try_ssl!(ffi::DSA_sign(hash.as_nid() as c_int,
|
|
||||||
message.as_ptr(),
|
|
||||||
message.len() as c_int,
|
|
||||||
sig.as_mut_ptr(),
|
|
||||||
&mut sig_len,
|
|
||||||
self.0));
|
|
||||||
sig.set_len(sig_len as usize);
|
|
||||||
sig.shrink_to_fit();
|
|
||||||
Ok(sig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let result = ffi::DSA_verify(hash.as_nid() as c_int,
|
|
||||||
message.as_ptr(),
|
|
||||||
message.len() as c_int,
|
|
||||||
sig.as_ptr(),
|
|
||||||
sig.len() as c_int,
|
|
||||||
self.0);
|
|
||||||
|
|
||||||
try_ssl_if!(result == -1);
|
|
||||||
Ok(result == 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_ptr(&self) -> *mut ffi::DSA {
|
pub fn as_ptr(&self) -> *mut ffi::DSA {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
@ -282,76 +247,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_generate() {
|
pub fn test_generate() {
|
||||||
let key = DSA::generate(1024).unwrap();
|
DSA::generate(1024).unwrap();
|
||||||
|
|
||||||
key.public_key_to_pem().unwrap();
|
|
||||||
key.private_key_to_pem().unwrap();
|
|
||||||
|
|
||||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
|
||||||
|
|
||||||
let digest = {
|
|
||||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
|
||||||
sha.write_all(&input).unwrap();
|
|
||||||
sha.finish().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let sig = key.sign(Type::SHA1, &digest).unwrap();
|
|
||||||
let verified = key.verify(Type::SHA1, &digest, &sig).unwrap();
|
|
||||||
assert!(verified);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn test_sign_verify() {
|
|
||||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
|
||||||
|
|
||||||
let private_key = {
|
|
||||||
let key = include_bytes!("../../test/dsa.pem");
|
|
||||||
DSA::private_key_from_pem(key).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let public_key = {
|
|
||||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
|
||||||
DSA::public_key_from_pem(key).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let digest = {
|
|
||||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
|
||||||
sha.write_all(&input).unwrap();
|
|
||||||
sha.finish().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let sig = private_key.sign(Type::SHA1, &digest).unwrap();
|
|
||||||
let verified = public_key.verify(Type::SHA1, &digest, &sig).unwrap();
|
|
||||||
assert!(verified);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn test_sign_verify_fail() {
|
|
||||||
let input: Vec<u8> = (0..25).cycle().take(128).collect();
|
|
||||||
let private_key = {
|
|
||||||
let key = include_bytes!("../../test/dsa.pem");
|
|
||||||
DSA::private_key_from_pem(key).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let public_key = {
|
|
||||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
|
||||||
DSA::public_key_from_pem(key).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let digest = {
|
|
||||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
|
||||||
sha.write_all(&input).unwrap();
|
|
||||||
sha.finish().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut sig = private_key.sign(Type::SHA1, &digest).unwrap();
|
|
||||||
// tamper with the sig this should cause a failure
|
|
||||||
let len = sig.len();
|
|
||||||
sig[len / 2] = 0;
|
|
||||||
sig[len - 1] = 0;
|
|
||||||
if let Ok(true) = public_key.verify(Type::SHA1, &digest, &sig) {
|
|
||||||
panic!("Tampered with signatures should not verify!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::mem;
|
||||||
use ffi;
|
use ffi;
|
||||||
|
|
||||||
use bio::{MemBio, MemBioSlice};
|
use bio::{MemBio, MemBioSlice};
|
||||||
|
use crypto::dsa::DSA;
|
||||||
use crypto::rsa::RSA;
|
use crypto::rsa::RSA;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use crypto::util::{CallbackState, invoke_passwd_cb};
|
use crypto::util::{CallbackState, invoke_passwd_cb};
|
||||||
|
|
@ -26,6 +27,17 @@ impl PKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new `PKey` containing a DSA key.
|
||||||
|
pub fn from_dsa(dsa: DSA) -> Result<PKey, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
||||||
|
let pkey = PKey(evp);
|
||||||
|
try_ssl!(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DSA, dsa.as_ptr() as *mut _));
|
||||||
|
mem::forget(dsa);
|
||||||
|
Ok(pkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new `PKey` containing an HMAC key.
|
/// Create a new `PKey` containing an HMAC key.
|
||||||
pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> {
|
pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,8 @@ impl<'a> Signer<'a> {
|
||||||
let mut buf = vec![0; len];
|
let mut buf = vec![0; len];
|
||||||
try_ssl_if!(ffi::EVP_DigestSignFinal(self.0, buf.as_mut_ptr() as *mut _, &mut len)
|
try_ssl_if!(ffi::EVP_DigestSignFinal(self.0, buf.as_mut_ptr() as *mut _, &mut len)
|
||||||
!= 1);
|
!= 1);
|
||||||
|
// The advertised length is not always equal to the real length for things like DSA
|
||||||
|
buf.truncate(len);
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +215,7 @@ mod test {
|
||||||
use crypto::hash::Type;
|
use crypto::hash::Type;
|
||||||
use crypto::sign::{Signer, Verifier};
|
use crypto::sign::{Signer, Verifier};
|
||||||
use crypto::rsa::RSA;
|
use crypto::rsa::RSA;
|
||||||
|
use crypto::dsa::DSA;
|
||||||
use crypto::pkey::PKey;
|
use crypto::pkey::PKey;
|
||||||
|
|
||||||
static INPUT: &'static [u8] =
|
static INPUT: &'static [u8] =
|
||||||
|
|
@ -240,7 +243,7 @@ mod test {
|
||||||
112, 223, 200, 163, 42, 70, 149, 67, 208, 25, 238, 251, 71];
|
112, 223, 200, 163, 42, 70, 149, 67, 208, 25, 238, 251, 71];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sign() {
|
fn rsa_sign() {
|
||||||
let key = include_bytes!("../../test/rsa.pem");
|
let key = include_bytes!("../../test/rsa.pem");
|
||||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||||
|
|
@ -253,7 +256,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_ok() {
|
fn rsa_verify_ok() {
|
||||||
let key = include_bytes!("../../test/rsa.pem");
|
let key = include_bytes!("../../test/rsa.pem");
|
||||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||||
|
|
@ -264,7 +267,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_invalid() {
|
fn rsa_verify_invalid() {
|
||||||
let key = include_bytes!("../../test/rsa.pem");
|
let key = include_bytes!("../../test/rsa.pem");
|
||||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||||
|
|
@ -275,6 +278,56 @@ mod test {
|
||||||
assert!(!verifier.finish(SIGNATURE).unwrap());
|
assert!(!verifier.finish(SIGNATURE).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn dsa_sign_verify() {
|
||||||
|
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||||
|
|
||||||
|
let private_key = {
|
||||||
|
let key = include_bytes!("../../test/dsa.pem");
|
||||||
|
PKey::from_dsa(DSA::private_key_from_pem(key).unwrap()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let public_key = {
|
||||||
|
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||||
|
PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
|
||||||
|
signer.update(&input).unwrap();
|
||||||
|
let sig = signer.finish().unwrap();
|
||||||
|
|
||||||
|
let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
|
||||||
|
verifier.update(&input).unwrap();
|
||||||
|
assert!(verifier.finish(&sig).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn dsa_sign_verify_fail() {
|
||||||
|
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||||
|
|
||||||
|
let private_key = {
|
||||||
|
let key = include_bytes!("../../test/dsa.pem");
|
||||||
|
PKey::from_dsa(DSA::private_key_from_pem(key).unwrap()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let public_key = {
|
||||||
|
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||||
|
PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
|
||||||
|
signer.update(&input).unwrap();
|
||||||
|
let mut sig = signer.finish().unwrap();
|
||||||
|
sig[0] -= 1;
|
||||||
|
|
||||||
|
let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
|
||||||
|
verifier.update(&input).unwrap();
|
||||||
|
match verifier.finish(&sig) {
|
||||||
|
Ok(true) => panic!("unexpected success"),
|
||||||
|
Ok(false) | Err(_) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
|
fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
|
||||||
for &(ref key, ref data, ref res) in tests.iter() {
|
for &(ref key, ref data, ref res) in tests.iter() {
|
||||||
let pkey = PKey::hmac(key).unwrap();
|
let pkey = PKey::hmac(key).unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue