diff --git a/sgx_crypto_helper/Cargo.toml b/sgx_crypto_helper/Cargo.toml index 1f37036b6..2c1724191 100644 --- a/sgx_crypto_helper/Cargo.toml +++ b/sgx_crypto_helper/Cargo.toml @@ -14,21 +14,25 @@ crate-type = ["staticlib","rlib"] [features] default = ["ucrypto_help"] +rsa2048 = [] +crypto = [] ucrypto_help = [ - "sgx_ucrypto", + # "sgx_ucrypto", "libc", "serde", "serde_derive", "serde-big-array"] mesalock_sgx = [ - "sgx_tcrypto", + # "sgx_tcrypto", "sgx_tstd", "serde-sgx", "serde_derive-sgx", "serde-big-array-sgx"] +# impl encrypt_buffer/etc WIHOUT using sgx_ucrypto nor sgx_tcrypto +crypto_direct = ["rsa", "sha2", "rand", "num-bigint"] [dependencies] -sgx_ucrypto = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +# sgx_ucrypto = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } libc = { version = "0.2", optional = true } itertools = { version = "*", default-features = false } serde = { version = "1.0.104", optional = true } @@ -37,9 +41,21 @@ serde-big-array = { version = "0.1", optional = true } serde-sgx = { git = "https://github.com/mesalock-linux/serde-sgx", package = 'serde', optional = true } serde_derive-sgx = { git = "https://github.com/mesalock-linux/serde-sgx", package = 'serde_derive', optional = true } serde-big-array-sgx = { git = "https://github.com/mesalock-linux/serde-big-array-sgx", package = 'serde-big-array', optional = true } +rsa = { optional = true, version = "0.8", default-features = false } +sha2 = { optional = true, version = "0.10", default-features = false } +rand = { optional = true, version = "0.8" } +# SOME deps of our main libs(=imageproc) use "num v0.4.0" so we must default to an old version +# = note: struct `num_bigint::BigUint` and struct `rsa::BigUint` have similar names, but are actually distinct types +# note: struct `num_bigint::BigUint` is defined in crate `num_bigint` +# --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/num-bigint-0.4.3/src/biguint.rs:38:1 +# 38 | pub struct BigUint { +# | ^^^^^^^^^^^^^^^^^^ +# note: struct `rsa::BigUint` is defined in crate `num_bigint_dig` +# --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/num-bigint-dig-0.8.2/src/biguint.rs:94:1 +num-bigint = { optional = true, version = "0.8", default-features = false, package = "num-bigint-dig" } [target.'cfg(not(target_env = "sgx"))'.dependencies] -sgx_tcrypto = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +# sgx_tcrypto = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } sgx_tstd = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } sgx_types = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git" } diff --git a/sgx_crypto_helper/src/crypto_direct.rs b/sgx_crypto_helper/src/crypto_direct.rs new file mode 100644 index 000000000..364e3d942 --- /dev/null +++ b/sgx_crypto_helper/src/crypto_direct.rs @@ -0,0 +1,142 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License.. + +/// cf /teaclave-sgx-sdk/sgx_tcrypto/src/crypto.rs + +/// +/// Cryptographic Functions +/// +use core::cell::{Cell, RefCell}; +use core::mem; +use core::ops::{DerefMut, Drop}; +use core::ptr; +use num_bigint::BigUint; +use rsa::{Oaep, PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey}; +use sgx_types::marker::ContiguousMemory; +use sgx_types::*; + +pub struct SgxRsaPubKey { + key: RsaPublicKey, +} + +impl SgxRsaPubKey { + /// Normally it calls: "sgx_create_rsa_pub1_key" + /// sgx_create_rsa_pub1_key generates a public key of the desired RSA + /// cryptographic with the input RSA key components. + /// Syntax + /// sgx_status_t sgx_create_rsa_priv2_key( + /// int mod_size, + /// int exp_size, + /// const unsigned char *le_n, + /// const unsigned char *le_e, + /// void **new_pub_key1 + /// ); + /// Parameters + /// mod_size [in] + /// Size in bytes of the RSA key modulus. + /// exp_size [in] + /// Size in bytes of the RSA public exponent. + /// le_n [in] + /// Pointer to the RSA modulus buffer. + /// le_e [in] + /// Pointer to the RSA public exponent buffer. + /// new_pub_key1 [out] + /// Pointer to the generated RSA public key. + /// Return value + /// SGX_SUCCESS + /// The RSA public key is successfully generated. + /// SGX_ERROR_INVALID_PARAMETER + /// Some of the pointers is NULL, or the input size is less than 0. + /// SGX_ERROR_UNEXPECTED + /// Unexpected error occurs during generating the RSA public key. + pub fn new(mod_size: i32, exp_size: i32, n: &[u8], e: &[u8]) -> SgxRsaPubKey { + assert!( + mod_size as usize == n.len(), + "SgxRsaPubKey::new: wrong modulus length??" + ); + assert!( + exp_size as usize == e.len(), + "SgxRsaPubKey::new: wrong exponent length??" + ); + SgxRsaPubKey { + // TODO when to choose from_bytes_be? platform? feature? never? + // [interstellar] DO NOT change without testing! This would completely break `integritee-cli`! + key: RsaPublicKey::new(BigUint::from_bytes_le(n), BigUint::from_bytes_le(e)) + .map_err(|err| sgx_status_t::SGX_ERROR_INVALID_PARAMETER) + .unwrap(), + } + } + + /// Normally it calls: "sgx_rsa_pub_encrypt_sha256" + /// sgx_rsa_pub_encrypt_sha256 performs RSA-OAEP encryption oper- + /// ation, with SHA-256 algorithm + /// sgx_status_t sgx_rsa_pub_encrypt_sha256( + /// void* rsa_key, + /// unsigned char* pout_data, + /// size_t* pout_len, + /// const unsigned char* pin_data, + /// const size_t pin_len + /// ); + /// rsa_key [in] + /// Pointer to the RSA public key. + /// pout_data [out] + /// Pointer to the output cipher text buffer. + /// pout_len [out] + /// Length of the output cipher text buffer. + /// pin_data [in] + /// Pointer to the input data buffer. + /// pin_len [in] + /// Length of the input data buffer. + /// Return value + /// SGX_SUCCESS + /// All the outputs are generated successfully. + /// SGX_ERROR_INVALID_PARAMETER + /// Some of the pointers is NULL, or the input data size is 0. + /// SGX_ERROR_UNEXPECTED + /// Unexpected error occurs during performing encryption operation. + pub fn encrypt_sha256( + &self, + out_data: &mut [u8], + out_len: &mut usize, + in_data: &[u8], + ) -> SgxError { + let mut rng = rand::thread_rng(); + let padding = Oaep::new::(); + let enc_data = self + .key + .encrypt(&mut rng, padding, in_data) + .map_err(|err| sgx_status_t::SGX_ERROR_UNEXPECTED)?; + + *out_len = enc_data.len(); + out_data.copy_from_slice(&enc_data); + + Ok(()) + } +} + +// impl Default for SgxRsaPubKey { +// fn default() -> Self { +// Self::new() +// } +// } + +pub struct SgxRsaPrivKey { + key: RefCell, + mod_size: Cell, + exp_size: Cell, + createflag: Cell, +} diff --git a/sgx_crypto_helper/src/lib.rs b/sgx_crypto_helper/src/lib.rs index 16deecc2d..fa2871375 100644 --- a/sgx_crypto_helper/src/lib.rs +++ b/sgx_crypto_helper/src/lib.rs @@ -30,7 +30,6 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(clippy::too_many_arguments)] - #![cfg_attr(all(feature = "mesalock_sgx", not(target_env = "sgx")), no_std)] #![cfg_attr(target_env = "sgx", feature(rustc_private))] #![cfg_attr(test, feature(test))] @@ -39,27 +38,41 @@ #[macro_use] extern crate sgx_tstd as std; -extern crate sgx_types; #[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] extern crate sgx_tcrypto as crypto; -#[cfg(not(any(feature = "mesalock_sgx", target_env = "sgx")))] +extern crate sgx_types; +#[cfg(all( + feature = "crypto", + not(any(feature = "mesalock_sgx", target_env = "sgx")) +))] extern crate sgx_ucrypto as crypto; -use std::prelude::v1::*; -use sgx_types::SgxResult; +#[cfg(feature = "crypto_direct")] +mod crypto_direct; + +#[cfg(any(feature = "crypto"))] use crypto::SgxRsaPrivKey; +#[cfg(any(feature = "crypto"))] use crypto::SgxRsaPubKey; +use sgx_types::SgxResult; +use std::prelude::v1::*; /// A trait to express the ability to create a RSA keypair with default e /// (65537) or customized e, and to_privkey/to_pubkey, encryption/decryption API. pub trait RsaKeyPair { /// Create a new RSA keypair with default e = 65537. - fn new() -> SgxResult where Self: std::marker::Sized; + fn new() -> SgxResult + where + Self: std::marker::Sized; /// Create a new RSA keypair with customized e - fn new_with_e(e: u32) -> SgxResult where Self: std::marker::Sized; + fn new_with_e(e: u32) -> SgxResult + where + Self: std::marker::Sized; /// Get a private key instance typed `SgxRsaPrivKey` which is defined in sgx_tcrypto/sgx_ucrypto. + #[cfg(any(feature = "crypto"))] fn to_privkey(self) -> SgxResult; /// get a public key instance typed `SgxPubPrivKey` which is defined in sgx_tcrypto/sgx_ucrypto. + #[cfg(any(feature = "crypto"))] fn to_pubkey(self) -> SgxResult; /// Encrypt a u8 slice to a Vec. Returns the length of ciphertext if OK. fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec) -> SgxResult; @@ -67,15 +80,15 @@ pub trait RsaKeyPair { fn decrypt_buffer(self, ciphertext: &[u8], plaintext: &mut Vec) -> SgxResult; } -#[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] -extern crate serde_sgx; #[cfg(not(any(feature = "mesalock_sgx", target_env = "sgx")))] extern crate serde; - #[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] -extern crate serde_derive_sgx as serde_derive; +extern crate serde_sgx; + #[cfg(not(any(feature = "mesalock_sgx", target_env = "sgx")))] extern crate serde_derive; +#[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] +extern crate serde_derive_sgx as serde_derive; #[cfg(any(feature = "mesalock_sgx", target_env = "sgx"))] #[macro_use] @@ -84,5 +97,6 @@ extern crate serde_big_array_sgx as serde_big_array; #[macro_use] extern crate serde_big_array; +#[cfg(feature = "rsa2048")] pub mod rsa2048; pub mod rsa3072; diff --git a/sgx_crypto_helper/src/rsa3072.rs b/sgx_crypto_helper/src/rsa3072.rs index 381a4f2c6..c9c5386ca 100644 --- a/sgx_crypto_helper/src/rsa3072.rs +++ b/sgx_crypto_helper/src/rsa3072.rs @@ -1,15 +1,22 @@ +#[cfg(feature = "crypto")] use crypto::rsgx_create_rsa_key_pair; +#[cfg(feature = "crypto")] use crypto::{SgxRsaPrivKey, SgxRsaPubKey}; use itertools::Itertools; use sgx_types::sgx_status_t; use sgx_types::SgxResult; use sgx_types::{SGX_RSA3072_KEY_SIZE, SGX_RSA3072_PRI_EXP_SIZE, SGX_RSA3072_PUB_EXP_SIZE}; -pub const SGX_RSA3072_DEFAULT_E: [u8;SGX_RSA3072_PUB_EXP_SIZE] = [0x01, 0x00, 0x00, 0x01]; // 16777217 +pub const SGX_RSA3072_DEFAULT_E: [u8; SGX_RSA3072_PUB_EXP_SIZE] = [0x01, 0x00, 0x00, 0x01]; // 16777217 use std::fmt; -use std::prelude::v1::*; +#[cfg(feature = "crypto_direct")] +use crate::crypto_direct as crypto; +#[cfg(feature = "crypto_direct")] +use crypto::{SgxRsaPrivKey, SgxRsaPubKey}; + use crate::RsaKeyPair; use serde_derive::*; +use std::prelude::v1::*; big_array! { BigArray; } @@ -58,7 +65,6 @@ pub struct Rsa3072KeyPair { iqmp: [u8; SGX_RSA3072_KEY_SIZE / 2], } - impl Default for Rsa3072KeyPair { fn default() -> Self { Rsa3072KeyPair { @@ -76,7 +82,9 @@ impl Default for Rsa3072KeyPair { impl fmt::Debug for Rsa3072KeyPair { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, r#"Rsa3072KeyPair: {{ n:{:02X}, d:{:02X}, e:{:02X}, p:{:02X}, q:{:02X}, dmp1:{:02X}, dmq:{:02X}, iqmp:{:02X} }}"#, + write!( + f, + r#"Rsa3072KeyPair: {{ 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(""), @@ -84,10 +92,12 @@ impl fmt::Debug for Rsa3072KeyPair { self.q.iter().format(""), self.dmp1.iter().format(""), self.dmq1.iter().format(""), - self.iqmp.iter().format("")) + self.iqmp.iter().format("") + ) } } +#[cfg(feature = "crypto")] impl RsaKeyPair for Rsa3072KeyPair { fn new() -> SgxResult { let mut newkey = Self::default(); @@ -197,7 +207,7 @@ impl RsaKeyPair for Rsa3072KeyPair { for i in 0..count { let cipher_slice = &ciphertext[i * bs..i * bs + bs]; - let plain_slice = &mut vec![0;bs_plain]; + let plain_slice = &mut vec![0; bs_plain]; let mut plain_len = bs_plain; privkey.decrypt_sha256(plain_slice, &mut plain_len, cipher_slice)?; @@ -209,6 +219,18 @@ impl RsaKeyPair for Rsa3072KeyPair { } } +// TODO or directly "impl RsaKeyPair"? +#[cfg(feature = "crypto_direct")] +impl Rsa3072KeyPair { + pub fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec) -> SgxResult { + todo!("Rsa3072KeyPair/crypto_direct::encrypt_buffer") + } + + pub fn decrypt_buffer(self, ciphertext: &[u8], plaintext: &mut Vec) -> SgxResult { + todo!("Rsa3072KeyPair/crypto_direct::decrypt_buffer") + } +} + impl Rsa3072KeyPair { pub fn export_pubkey(self) -> SgxResult { Ok(Rsa3072PubKey { @@ -244,6 +266,7 @@ impl Default for Rsa3072PubKey { } impl Rsa3072PubKey { + #[cfg(feature = "crypto")] fn to_pubkey(self) -> SgxResult { let result = SgxRsaPubKey::new(); match result.create( @@ -257,6 +280,20 @@ impl Rsa3072PubKey { } } + #[cfg(feature = "crypto_direct")] + fn to_pubkey(self) -> SgxResult { + let mut result = SgxRsaPubKey::new( + SGX_RSA3072_KEY_SIZE as i32, + SGX_RSA3072_PUB_EXP_SIZE as i32, + &self.n, + &self.e, + ); + + Ok(result) + // TODO + // Err(x) => Err(x), + } + pub fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec) -> SgxResult { let pubkey = self.to_pubkey()?; let bs = 384; @@ -280,26 +317,32 @@ impl Rsa3072PubKey { impl fmt::Debug for Rsa3072PubKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, r#"Rsa3072KeyPair: {{ n:{:02X}, e:{:02X} }}"#, + write!( + f, + r#"Rsa3072KeyPair: {{ n:{:02X}, e:{:02X} }}"#, self.n.iter().format(""), - self.e.iter().format("")) + self.e.iter().format("") + ) } } #[cfg(test)] mod tests { - extern crate rdrand; extern crate rand_core; + extern crate rdrand; extern crate test; - use self::test::Bencher; - use self::rdrand::RdRand; use self::rand_core::RngCore; - use crate::RsaKeyPair; + use self::rdrand::RdRand; + use self::test::Bencher; use crate::rsa3072::Rsa3072KeyPair; use crate::rsa3072::Rsa3072PubKey; + #[cfg(feature = "crypto")] use crate::rsa3072::SgxRsaPrivKey; + #[cfg(feature = "crypto")] use crate::rsa3072::SgxRsaPubKey; + use crate::RsaKeyPair; + #[cfg(feature = "crypto")] use crypto::rsgx_create_rsa_key_pair; use sgx_types::sgx_status_t; @@ -345,6 +388,7 @@ mod tests { assert!(keypair.to_privkey().is_ok()); } + #[cfg(feature = "crypto")] #[test] fn rsa_encrypt_decrypt() { let text = String::from("abc"); @@ -435,9 +479,12 @@ mod tests { let exported_pub_key = exported_pub_key.unwrap(); let serialized_pub_key = serde_json::to_string(&exported_pub_key).unwrap(); - let deserialized_pub_key: Rsa3072PubKey = serde_json::from_str(&serialized_pub_key).unwrap(); + let deserialized_pub_key: Rsa3072PubKey = + serde_json::from_str(&serialized_pub_key).unwrap(); - assert!(deserialized_pub_key.encrypt_buffer(&plaintext, &mut ciphertext).is_ok()); + assert!(deserialized_pub_key + .encrypt_buffer(&plaintext, &mut ciphertext) + .is_ok()); let mut decrypted: Vec = Vec::new(); assert!(kp.decrypt_buffer(&ciphertext, &mut decrypted).is_ok()); assert_eq!("T".repeat(1000), String::from_utf8(decrypted).unwrap()); @@ -446,7 +493,7 @@ mod tests { #[bench] fn encrypt_speed_bench(b: &mut Bencher) { let mut rng = RdRand::new().unwrap(); - let mut buffer = vec![0;1*1024*1024]; + let mut buffer = vec![0; 1 * 1024 * 1024]; let kp = Rsa3072KeyPair::new().unwrap(); let mut ciphertext: Vec = Vec::new(); rng.fill_bytes(&mut buffer); @@ -456,7 +503,7 @@ mod tests { #[bench] fn decrypt_speed_bench(b: &mut Bencher) { let mut rng = RdRand::new().unwrap(); - let mut buffer = vec![0;1*1024*1024]; + let mut buffer = vec![0; 1 * 1024 * 1024]; let kp = Rsa3072KeyPair::new().unwrap(); let mut ciphertext: Vec = Vec::new(); rng.fill_bytes(&mut buffer);