| use crypto::rsgx_create_rsa_key_pair; |
| use crypto::{SgxRsaPrivKey, SgxRsaPubKey}; |
| use itertools::Itertools; |
| use sgx_types::{sgx_status_t, size_t, SgxResult}; |
| pub const SGX_RSA2048_KEY_SIZE: size_t = 256; |
| pub const SGX_RSA2048_PRI_EXP_SIZE: size_t = 256; |
| pub const SGX_RSA2048_PUB_EXP_SIZE: size_t = 4; |
| pub const SGX_RSA2048_DEFAULT_E: [u8;SGX_RSA2048_PUB_EXP_SIZE] = [0x01, 0x00, 0x00, 0x01]; // 65537 |
| use std::fmt; |
| |
| use std::prelude::v1::*; |
| use crate::RsaKeyPair; |
| use serde_derive::*; |
| |
| big_array! { BigArray; } |
| |
| /// Data structure of RSA 2048 Keypair (RSA-OAEP). |
| /// RSA 2048 Keypair provides block cipher encryption/decryption |
| /// implementations. The block size of plain text is 190 bytes |
| /// and the block size of cipher text is 256 bytes. |
| /// 190 byte = 2048bit - 2*SHA256_BYTE - 2 |
| #[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] |
| #[derive(Serialize, Deserialize, Clone, Copy)] |
| #[serde(crate = "serde_sgx")] |
| pub struct Rsa2048KeyPair { |
| #[serde(with = "BigArray")] |
| n: [u8; SGX_RSA2048_KEY_SIZE], |
| #[serde(with = "BigArray")] |
| d: [u8; SGX_RSA2048_PRI_EXP_SIZE], |
| e: [u8; SGX_RSA2048_PUB_EXP_SIZE], |
| #[serde(with = "BigArray")] |
| p: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| q: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| dmp1: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| dmq1: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| iqmp: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| } |
| #[cfg(not(any(feature = "mesalock_sgx", target_env = "sgx")))] |
| #[derive(Serialize, Deserialize, Clone, Copy)] |
| pub struct Rsa2048KeyPair { |
| #[serde(with = "BigArray")] |
| n: [u8; SGX_RSA2048_KEY_SIZE], |
| #[serde(with = "BigArray")] |
| d: [u8; SGX_RSA2048_PRI_EXP_SIZE], |
| e: [u8; SGX_RSA2048_PUB_EXP_SIZE], |
| #[serde(with = "BigArray")] |
| p: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| q: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| dmp1: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| dmq1: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| #[serde(with = "BigArray")] |
| iqmp: [u8; SGX_RSA2048_KEY_SIZE / 2], |
| } |
| |
| impl Default for Rsa2048KeyPair { |
| fn default() -> Self { |
| Rsa2048KeyPair { |
| n: [0; SGX_RSA2048_KEY_SIZE], |
| d: [0; SGX_RSA2048_PRI_EXP_SIZE], |
| e: SGX_RSA2048_DEFAULT_E, |
| p: [0; SGX_RSA2048_KEY_SIZE / 2], |
| q: [0; SGX_RSA2048_KEY_SIZE / 2], |
| dmp1: [0; SGX_RSA2048_KEY_SIZE / 2], |
| dmq1: [0; SGX_RSA2048_KEY_SIZE / 2], |
| iqmp: [0; SGX_RSA2048_KEY_SIZE / 2], |
| } |
| } |
| } |
| |
| impl fmt::Debug for Rsa2048KeyPair { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, r#"Rsa2048KeyPair: {{ n:{:02X}, d:{:02X}, e:{:02X}, p:{:02X}, q:{:02X}, dmp1:{:02X}, dmq:{:02X}, iqmp:{:02X} }}"#, |
| self.n.iter().format(""), |
| self.d.iter().format(""), |
| self.e.iter().format(""), |
| self.p.iter().format(""), |
| self.q.iter().format(""), |
| self.dmp1.iter().format(""), |
| self.dmq1.iter().format(""), |
| self.iqmp.iter().format("")) |
| } |
| } |
| |
| impl RsaKeyPair for Rsa2048KeyPair { |
| fn new() -> SgxResult<Self> { |
| let mut newkey = Self::default(); |
| match rsgx_create_rsa_key_pair( |
| SGX_RSA2048_KEY_SIZE as i32, |
| SGX_RSA2048_PUB_EXP_SIZE as i32, |
| &mut newkey.n, |
| &mut newkey.d, |
| &mut newkey.e, |
| &mut newkey.p, |
| &mut newkey.q, |
| &mut newkey.dmp1, |
| &mut newkey.dmq1, |
| &mut newkey.iqmp, |
| ) { |
| Ok(()) => Ok(newkey), |
| Err(x) => Err(x), |
| } |
| } |
| |
| fn new_with_e(e: u32) -> SgxResult<Self> { |
| let mut newkey = Self::default(); |
| newkey.e = e.to_le_bytes(); |
| match rsgx_create_rsa_key_pair( |
| SGX_RSA2048_KEY_SIZE as i32, |
| SGX_RSA2048_PUB_EXP_SIZE as i32, |
| &mut newkey.n, |
| &mut newkey.d, |
| &mut newkey.e, |
| &mut newkey.p, |
| &mut newkey.q, |
| &mut newkey.dmp1, |
| &mut newkey.dmq1, |
| &mut newkey.iqmp, |
| ) { |
| Ok(()) => Ok(newkey), |
| Err(x) => Err(x), |
| } |
| } |
| |
| fn to_privkey(self) -> SgxResult<SgxRsaPrivKey> { |
| let result = SgxRsaPrivKey::new(); |
| match result.create( |
| SGX_RSA2048_KEY_SIZE as i32, |
| SGX_RSA2048_PRI_EXP_SIZE as i32, |
| &self.e, |
| &self.p, |
| &self.q, |
| &self.dmp1, |
| &self.dmq1, |
| &self.iqmp, |
| ) { |
| Ok(()) => Ok(result), |
| Err(x) => Err(x), |
| } |
| } |
| |
| fn to_pubkey(self) -> SgxResult<SgxRsaPubKey> { |
| let result = SgxRsaPubKey::new(); |
| match result.create( |
| SGX_RSA2048_KEY_SIZE as i32, |
| SGX_RSA2048_PUB_EXP_SIZE as i32, |
| &self.n, |
| &self.e, |
| ) { |
| Ok(()) => Ok(result), |
| Err(x) => Err(x), |
| } |
| } |
| |
| fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec<u8>) -> SgxResult<usize> { |
| let pubkey = self.to_pubkey()?; |
| let bs = 256; |
| |
| // The magic number 190 comes from RSA-OAEP: |
| // #define RSA_2048_KEY_BYTE 256 |
| // #define SHA_SIZE_BIT 256 |
| // #define RSAOAEP_ENCRYPT_MAXLEN RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 /* 190 */ |
| // RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 |
| let bs_plain = bs - 2 * 256 / 8 - 2; |
| let count = (plaintext.len() + bs_plain - 1) / bs_plain; |
| ciphertext.resize(bs * count, 0); |
| |
| for i in 0..count { |
| let cipher_slice = &mut ciphertext[i * bs..i * bs + bs]; |
| let mut out_len = bs; |
| let plain_slice = |
| &plaintext[i * bs_plain..std::cmp::min(i * bs_plain + bs_plain, plaintext.len())]; |
| |
| pubkey.encrypt_sha256(cipher_slice, &mut out_len, plain_slice)?; |
| } |
| |
| Ok(ciphertext.len()) |
| } |
| |
| fn decrypt_buffer(self, ciphertext: &[u8], plaintext: &mut Vec<u8>) -> SgxResult<usize> { |
| let privkey = self.to_privkey()?; |
| let bs = 256; |
| if ciphertext.len() % bs != 0 { |
| return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER); |
| } |
| // The magic number 190 comes from RSA-OAEP: |
| // #define RSA_2048_KEY_BYTE 256 |
| // #define SHA_SIZE_BIT 256 |
| // #define RSAOAEP_ENCRYPT_MAXLEN RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 /* 190 */ |
| // RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 |
| //let bs_plain = 256 - 2 * 256 / 8 - 2; |
| let bs_plain = bs; |
| let count = ciphertext.len() / bs; |
| plaintext.clear(); |
| |
| for i in 0..count { |
| let cipher_slice = &ciphertext[i * bs..i * bs + bs]; |
| let plain_slice = &mut vec![0;bs_plain]; |
| let mut plain_len = bs_plain; |
| |
| privkey.decrypt_sha256(plain_slice, &mut plain_len, cipher_slice)?; |
| let mut decoded_vec = plain_slice[..plain_len].to_vec(); |
| plaintext.append(&mut decoded_vec); |
| } |
| |
| Ok(plaintext.len()) |
| } |
| |
| } |
| |
| impl Rsa2048KeyPair { |
| pub fn export_pubkey(self) -> SgxResult<Rsa2048PubKey> { |
| Ok(Rsa2048PubKey { |
| n: self.n, |
| e: self.e, |
| }) |
| } |
| } |
| |
| #[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] |
| #[derive(Serialize, Deserialize, Clone, Copy)] |
| #[serde(crate = "serde_sgx")] |
| pub struct Rsa2048PubKey { |
| #[serde(with = "BigArray")] |
| n: [u8; SGX_RSA2048_KEY_SIZE], |
| e: [u8; SGX_RSA2048_PUB_EXP_SIZE], |
| } |
| #[cfg(not(any(feature = "mesalock_sgx", target_env = "sgx")))] |
| #[derive(Serialize, Deserialize, Clone, Copy)] |
| pub struct Rsa2048PubKey { |
| #[serde(with = "BigArray")] |
| n: [u8; SGX_RSA2048_KEY_SIZE], |
| e: [u8; SGX_RSA2048_PUB_EXP_SIZE], |
| } |
| |
| impl Default for Rsa2048PubKey { |
| fn default() -> Self { |
| Rsa2048PubKey { |
| n: [0; SGX_RSA2048_KEY_SIZE], |
| e: SGX_RSA2048_DEFAULT_E, |
| } |
| } |
| } |
| |
| impl Rsa2048PubKey { |
| pub fn to_pubkey(self) -> SgxResult<SgxRsaPubKey> { |
| let result = SgxRsaPubKey::new(); |
| match result.create( |
| SGX_RSA2048_KEY_SIZE as i32, |
| SGX_RSA2048_PUB_EXP_SIZE as i32, |
| &self.n, |
| &self.e, |
| ) { |
| Ok(()) => Ok(result), |
| Err(x) => Err(x), |
| } |
| } |
| |
| pub fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec<u8>) -> SgxResult<usize> { |
| let pubkey = self.to_pubkey()?; |
| let bs = 256; |
| |
| // The magic number 190 comes from RSA-OAEP: |
| // #define RSA_2048_KEY_BYTE 256 |
| // #define SHA_SIZE_BIT 256 |
| // #define RSAOAEP_ENCRYPT_MAXLEN RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 /* 190 */ |
| // RSA_2048_KEY_BYTE - 2*SHA_SIZE_BIT/8 - 2 |
| let bs_plain = bs - 2 * 256 / 8 - 2; |
| let count = (plaintext.len() + bs_plain - 1) / bs_plain; |
| ciphertext.resize(bs * count, 0); |
| |
| for i in 0..count { |
| let cipher_slice = &mut ciphertext[i * bs..i * bs + bs]; |
| let mut out_len = bs; |
| let plain_slice = |
| &plaintext[i * bs_plain..std::cmp::min(i * bs_plain + bs_plain, plaintext.len())]; |
| |
| pubkey.encrypt_sha256(cipher_slice, &mut out_len, plain_slice)?; |
| } |
| |
| Ok(ciphertext.len()) |
| } |
| } |
| |
| impl fmt::Debug for Rsa2048PubKey { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, r#"Rsa2048KeyPair: {{ n:{:02X}, e:{:02X} }}"#, |
| self.n.iter().format(""), |
| self.e.iter().format("")) |
| } |
| } |
| |
| |
| #[cfg(test)] |
| mod tests { |
| extern crate rdrand; |
| extern crate rand_core; |
| extern crate test; |
| |
| use self::rdrand::RdRand; |
| use self::rand_core::RngCore; |
| use crate::RsaKeyPair; |
| use crate::rsa2048::Rsa2048KeyPair; |
| use crate::rsa2048::Rsa2048PubKey; |
| use crate::rsa2048::SgxRsaPrivKey; |
| use crate::rsa2048::SgxRsaPubKey; |
| use crypto::rsgx_create_rsa_key_pair; |
| use sgx_types::sgx_status_t; |
| use self::test::Bencher; |
| |
| #[test] |
| fn rsa2048_new() { |
| let keypair = Rsa2048KeyPair::new(); |
| assert!(keypair.is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(3); |
| assert!(keypair.is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(65537); |
| assert!(keypair.is_ok()); |
| } |
| |
| #[test] |
| fn rsa2048_new_fail() { |
| let keypair = Rsa2048KeyPair::new_with_e(4); |
| assert_eq!(keypair.unwrap_err(), sgx_status_t::SGX_ERROR_UNEXPECTED); |
| let keypair = Rsa2048KeyPair::new_with_e(65536); |
| assert_eq!(keypair.unwrap_err(), sgx_status_t::SGX_ERROR_UNEXPECTED); } |
| |
| #[test] |
| fn rsa2048_to_sgx_rsa_pub_key() { |
| let keypair = Rsa2048KeyPair::default(); |
| assert!(keypair.to_pubkey().is_err()); |
| let keypair = Rsa2048KeyPair::new().unwrap(); |
| assert!(keypair.to_pubkey().is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(3).unwrap(); |
| assert!(keypair.to_pubkey().is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(65537).unwrap(); |
| assert!(keypair.to_pubkey().is_ok()); |
| } |
| |
| #[test] |
| fn rsa2048_to_sgx_rsa_priv_key() { |
| let keypair = Rsa2048KeyPair::default(); |
| assert!(keypair.to_privkey().is_err()); |
| let keypair = Rsa2048KeyPair::new().unwrap(); |
| assert!(keypair.to_privkey().is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(3).unwrap(); |
| assert!(keypair.to_privkey().is_ok()); |
| let keypair = Rsa2048KeyPair::new_with_e(65537).unwrap(); |
| assert!(keypair.to_privkey().is_ok()); |
| } |
| |
| #[test] |
| fn rsa_encrypt_decrypt() { |
| let text = String::from("abc"); |
| let text_slice = &text.into_bytes(); |
| |
| let mod_size: i32 = 256; |
| let exp_size: i32 = 4; |
| let mut n: Vec<u8> = vec![0_u8; mod_size as usize]; |
| let mut d: Vec<u8> = vec![0_u8; mod_size as usize]; |
| let mut e: Vec<u8> = vec![1, 0, 1, 0]; |
| let mut p: Vec<u8> = vec![0_u8; mod_size as usize / 2]; |
| let mut q: Vec<u8> = vec![0_u8; mod_size as usize / 2]; |
| let mut dmp1: Vec<u8> = vec![0_u8; mod_size as usize / 2]; |
| let mut dmq1: Vec<u8> = vec![0_u8; mod_size as usize / 2]; |
| let mut iqmp: Vec<u8> = vec![0_u8; mod_size as usize / 2]; |
| |
| assert!(rsgx_create_rsa_key_pair( |
| mod_size, |
| exp_size, |
| n.as_mut_slice(), |
| d.as_mut_slice(), |
| e.as_mut_slice(), |
| p.as_mut_slice(), |
| q.as_mut_slice(), |
| dmp1.as_mut_slice(), |
| dmq1.as_mut_slice(), |
| iqmp.as_mut_slice() |
| ) |
| .is_ok()); |
| |
| let privkey = SgxRsaPrivKey::new(); |
| let pubkey = SgxRsaPubKey::new(); |
| |
| assert!(pubkey |
| .create(mod_size, exp_size, n.as_slice(), e.as_slice()) |
| .is_ok()); |
| |
| assert!(privkey |
| .create( |
| mod_size, |
| exp_size, |
| e.as_slice(), |
| p.as_slice(), |
| q.as_slice(), |
| dmp1.as_slice(), |
| dmq1.as_slice(), |
| iqmp.as_slice() |
| ) |
| .is_ok()); |
| |
| let mut ciphertext: Vec<u8> = vec![0_u8; 256]; |
| let mut chipertext_len: usize = ciphertext.len(); |
| assert!(pubkey |
| .encrypt_sha256(ciphertext.as_mut_slice(), &mut chipertext_len, text_slice) |
| .is_ok()); |
| |
| let mut plaintext: Vec<u8> = vec![0_u8; 256]; |
| let mut plaintext_len: usize = plaintext.len(); |
| assert!(privkey |
| .decrypt_sha256( |
| plaintext.as_mut_slice(), |
| &mut plaintext_len, |
| ciphertext.as_slice() |
| ) |
| .is_ok()); |
| |
| assert_eq!(plaintext[..plaintext_len], text_slice[..]) |
| } |
| |
| #[test] |
| fn buffer_enc_dec() { |
| let plaintext: Vec<u8> = "A".repeat(1000).into_bytes(); |
| let mut ciphertext: Vec<u8> = Vec::new(); |
| let kp = Rsa2048KeyPair::new().unwrap(); |
| assert!(kp.encrypt_buffer(&plaintext, &mut ciphertext).is_ok()); |
| let mut decrypted: Vec<u8> = Vec::new(); |
| assert!(kp.decrypt_buffer(&ciphertext, &mut decrypted).is_ok()); |
| assert_eq!("A".repeat(1000), String::from_utf8(decrypted).unwrap()); |
| } |
| |
| #[test] |
| fn export_test() { |
| let plaintext: Vec<u8> = "T".repeat(1000).into_bytes(); |
| let mut ciphertext: Vec<u8> = Vec::new(); |
| let kp = Rsa2048KeyPair::new().unwrap(); |
| let exported_pub_key = kp.export_pubkey(); |
| assert!(exported_pub_key.is_ok()); |
| |
| let exported_pub_key = exported_pub_key.unwrap(); |
| let serialized_pub_key = serde_json::to_string(&exported_pub_key).unwrap(); |
| let deserialized_pub_key: Rsa2048PubKey = serde_json::from_str(&serialized_pub_key).unwrap(); |
| |
| assert!(deserialized_pub_key.encrypt_buffer(&plaintext, &mut ciphertext).is_ok()); |
| let mut decrypted: Vec<u8> = Vec::new(); |
| assert!(kp.decrypt_buffer(&ciphertext, &mut decrypted).is_ok()); |
| assert_eq!("T".repeat(1000), String::from_utf8(decrypted).unwrap()); |
| } |
| |
| #[bench] |
| fn encrypt_speed_bench(b: &mut Bencher) { |
| let mut rng = RdRand::new().unwrap(); |
| let mut buffer = vec![0;1*1024*1024]; |
| let kp = Rsa2048KeyPair::new().unwrap(); |
| let mut ciphertext: Vec<u8> = Vec::new(); |
| rng.fill_bytes(&mut buffer); |
| b.iter(|| kp.encrypt_buffer(&buffer, &mut ciphertext)); |
| } |
| |
| #[bench] |
| fn decrypt_speed_bench(b: &mut Bencher) { |
| let mut rng = RdRand::new().unwrap(); |
| let mut buffer = vec![0;1*1024*1024]; |
| let kp = Rsa2048KeyPair::new().unwrap(); |
| let mut ciphertext: Vec<u8> = Vec::new(); |
| rng.fill_bytes(&mut buffer); |
| kp.encrypt_buffer(&buffer, &mut ciphertext).unwrap(); |
| let mut decrypted: Vec<u8> = Vec::new(); |
| b.iter(|| kp.decrypt_buffer(&ciphertext, &mut decrypted)); |
| } |
| } |