diff options
Diffstat (limited to 'openssl/src/crypto')
| -rw-r--r-- | openssl/src/crypto/hmac.rs | 22 | ||||
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 127 | ||||
| -rw-r--r-- | openssl/src/crypto/symm.rs | 9 |
3 files changed, 131 insertions, 27 deletions
diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 5c9f7576..2c329c1b 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -21,6 +21,7 @@ use std::io::prelude::*; use crypto::hash::Type; use ffi; +use ffi_extras; #[derive(PartialEq, Copy, Clone)] enum State { @@ -88,9 +89,10 @@ impl HMAC { #[inline] fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { unsafe { - let r = ffi::HMAC_Init_ex(&mut self.ctx, - key.as_ptr(), key.len() as c_int, - md, 0 as *const _); + let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, + key.as_ptr(), + key.len() as c_int, + md, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -106,9 +108,9 @@ impl HMAC { // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { - let r = ffi::HMAC_Init_ex(&mut self.ctx, - 0 as *const _, 0, - 0 as *const _, 0 as *const _); + let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, + 0 as *const _, 0, + 0 as *const _, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -120,7 +122,7 @@ impl HMAC { self.init(); } unsafe { - let r = ffi::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); + let r = ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); } self.state = Updated; @@ -135,7 +137,7 @@ impl HMAC { let mut res: Vec<u8> = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; - let r = ffi::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); + let r = ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); @@ -168,7 +170,7 @@ impl Clone for HMAC { let mut ctx: ffi::HMAC_CTX; unsafe { ctx = ::std::mem::uninitialized(); - let r = ffi::HMAC_CTX_copy(&mut ctx, &self.ctx); + let r = ffi_extras::HMAC_CTX_copy(&mut ctx, &self.ctx); assert_eq!(r, 1); } HMAC { ctx: ctx, type_: self.type_, state: self.state } @@ -181,7 +183,7 @@ impl Drop for HMAC { if self.state != Finalized { let mut buf: Vec<u8> = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; - ffi::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); + ffi_extras::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); } ffi::HMAC_CTX_cleanup(&mut self.ctx); } diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 695bd8a6..6ca0aa12 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -276,7 +276,36 @@ impl PKey { } } - pub fn encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { + pub fn private_encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { + unsafe { + let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + panic!("Could not get RSA key for encryption"); + } + let len = ffi::RSA_size(rsa); + + assert!(s.len() < self.max_data()); + + let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>(); + + let rv = ffi::RSA_private_encrypt( + s.len() as c_int, + s.as_ptr(), + r.as_mut_ptr(), + rsa, + openssl_padding_code(padding)); + + if rv < 0 as c_int { + // println!("{:?}", SslError::get()); + vec!() + } else { + r.truncate(rv as usize); + r + } + } + } + + pub fn public_encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); if rsa.is_null() { @@ -304,7 +333,7 @@ impl PKey { } } - pub fn decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { + pub fn private_decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); if rsa.is_null() { @@ -332,16 +361,78 @@ impl PKey { } } + pub fn public_decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { + unsafe { + let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + panic!("Could not get RSA key for decryption"); + } + let len = ffi::RSA_size(rsa); + + assert_eq!(s.len() as c_int, ffi::RSA_size(rsa)); + + let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>(); + + let rv = ffi::RSA_public_decrypt( + s.len() as c_int, + s.as_ptr(), + r.as_mut_ptr(), + rsa, + openssl_padding_code(padding)); + + if rv < 0 as c_int { + vec!() + } else { + r.truncate(rv as usize); + r + } + } + } + /** - * Encrypts data using OAEP padding, returning the encrypted data. The + * Encrypts data with the public key, using OAEP padding, returning the encrypted data. The * supplied data must not be larger than max_data(). */ - pub fn encrypt(&self, s: &[u8]) -> Vec<u8> { self.encrypt_with_padding(s, EncryptionPadding::OAEP) } + pub fn encrypt(&self, s: &[u8]) -> Vec<u8> { self.public_encrypt_with_padding(s, EncryptionPadding::OAEP) } + + /** + * Encrypts data with the public key, using provided padding, returning the encrypted data. The + * supplied data must not be larger than max_data(). + */ + pub fn encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { self.public_encrypt_with_padding(s, padding) } + + /** + * Encrypts data with the public key, using OAEP padding, returning the encrypted data. The + * supplied data must not be larger than max_data(). + */ + pub fn public_encrypt(&self, s: &[u8]) -> Vec<u8> { self.public_encrypt_with_padding(s, EncryptionPadding::OAEP) } + + /** + * Decrypts data with the public key, using PKCS1v15 padding, returning the decrypted data. + */ + pub fn public_decrypt(&self, s: &[u8]) -> Vec<u8> { self.public_decrypt_with_padding(s, EncryptionPadding::PKCS1v15) } /** - * Decrypts data, expecting OAEP padding, returning the decrypted data. + * Decrypts data with the private key, expecting OAEP padding, returning the decrypted data. */ - pub fn decrypt(&self, s: &[u8]) -> Vec<u8> { self.decrypt_with_padding(s, EncryptionPadding::OAEP) } + pub fn decrypt(&self, s: &[u8]) -> Vec<u8> { self.private_decrypt_with_padding(s, EncryptionPadding::OAEP) } + + /** + * Decrypts data with the private key, using provided padding, returning the encrypted data. The + * supplied data must not be larger than max_data(). + */ + pub fn decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> { self.private_decrypt_with_padding(s, padding) } + + /** + * Decrypts data with the private key, expecting OAEP padding, returning the decrypted data. + */ + pub fn private_decrypt(&self, s: &[u8]) -> Vec<u8> { self.private_decrypt_with_padding(s, EncryptionPadding::OAEP) } + + /** + * Encrypts data with the private key, using PKCS1v15 padding, returning the encrypted data. The + * supplied data must not be larger than max_data(). + */ + pub fn private_encrypt(&self, s: &[u8]) -> Vec<u8> { self.private_encrypt_with_padding(s, EncryptionPadding::PKCS1v15) } /** * Signs data, using OpenSSL's default scheme and adding sha256 ASN.1 information to the @@ -493,26 +584,38 @@ mod tests { } #[test] - fn test_encrypt() { + fn test_private_encrypt() { + let mut k0 = super::PKey::new(); + let mut k1 = super::PKey::new(); + let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8); + k0.gen(512); + k1.load_pub(&k0.save_pub()); + let emsg = k0.private_encrypt(&msg); + let dmsg = k1.public_decrypt(&emsg); + assert!(msg == dmsg); + } + + #[test] + fn test_public_encrypt() { let mut k0 = super::PKey::new(); let mut k1 = super::PKey::new(); let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8); k0.gen(512); k1.load_pub(&k0.save_pub()); - let emsg = k1.encrypt(&msg); - let dmsg = k0.decrypt(&emsg); + let emsg = k1.public_encrypt(&msg); + let dmsg = k0.private_decrypt(&emsg); assert!(msg == dmsg); } #[test] - fn test_encrypt_pkcs() { + fn test_public_encrypt_pkcs() { let mut k0 = super::PKey::new(); let mut k1 = super::PKey::new(); let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8); k0.gen(512); k1.load_pub(&k0.save_pub()); - let emsg = k1.encrypt_with_padding(&msg, super::EncryptionPadding::PKCS1v15); - let dmsg = k0.decrypt_with_padding(&emsg, super::EncryptionPadding::PKCS1v15); + let emsg = k1.public_encrypt_with_padding(&msg, super::EncryptionPadding::PKCS1v15); + let dmsg = k0.private_decrypt_with_padding(&emsg, super::EncryptionPadding::PKCS1v15); assert!(msg == dmsg); } diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index db8aa54e..bc4b65b5 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -1,5 +1,4 @@ use std::iter::repeat; -use std::convert::AsRef; use libc::{c_int}; use crypto::symm_internal::evpc; @@ -75,7 +74,7 @@ impl Crypter { /** * Initializes this crypter. */ - pub fn init<T: AsRef<[u8]>>(&self, mode: Mode, key: &[u8], iv: T) { + pub fn init(&self, mode: Mode, key: &[u8], iv: &[u8]) { unsafe { let mode = match mode { Mode::Encrypt => 1 as c_int, @@ -87,7 +86,7 @@ impl Crypter { self.ctx, self.evp, key.as_ptr(), - iv.as_ref().as_ptr(), + iv.as_ptr(), mode ); } @@ -146,7 +145,7 @@ impl Drop for Crypter { * Encrypts data, using the specified crypter type in encrypt mode with the * specified key and iv; returns the resulting (encrypted) data. */ -pub fn encrypt<T: AsRef<[u8]>>(t: Type, key: &[u8], iv: T, data: &[u8]) -> Vec<u8> { +pub fn encrypt(t: Type, key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> { let c = Crypter::new(t); c.init(Mode::Encrypt, key, iv); let mut r = c.update(data); @@ -159,7 +158,7 @@ pub fn encrypt<T: AsRef<[u8]>>(t: Type, key: &[u8], iv: T, data: &[u8]) -> Vec<u * Decrypts data, using the specified crypter type in decrypt mode with the * specified key and iv; returns the resulting (decrypted) data. */ -pub fn decrypt<T: AsRef<[u8]>>(t: Type, key: &[u8], iv: T, data: &[u8]) -> Vec<u8> { +pub fn decrypt(t: Type, key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> { let c = Crypter::new(t); c.init(Mode::Decrypt, key, iv); let mut r = c.update(data); |