blob: 5bc3d4d8341d14af32bcc806f3ece4277d37973a [file] [log] [blame]
// 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..
//!
//! Cryptographic Functions
//!
use sgx_types::marker::ContiguousMemory;
use sgx_types::*;
use std::cell::{Cell, RefCell};
use std::mem;
use std::ops::{DerefMut, Drop};
use std::ptr;
///
/// The rsgx_sha256_msg function performs a standard SHA256 hash over the input data buffer.
///
/// # Description
///
/// The rsgx_sha256_msg function performs a standard SHA256 hash over the input data buffer.
/// Only a 256-bit version of the SHA hash is supported. (Other sizes, for example 512, are
/// not supported in this minimal cryptography library).
///
/// The function should be used if the complete input data stream is available.
/// Otherwise, the Init, Update… Update, Final procedure should be used to compute
/// a SHA256 bit hash over multiple input data sets.
///
/// # Parameters
///
/// **src**
///
/// A pointer to the input data stream to be hashed.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The 256-bit hash that has been SHA256 calculated
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Input pointers are invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The SHA256 hash calculation failed.
///
pub fn rsgx_sha256_msg<T>(src: &T) -> SgxResult<sgx_sha256_hash_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut hash = sgx_sha256_hash_t::default();
let ret = unsafe {
sgx_sha256_msg(
src as *const _ as *const u8,
size as u32,
&mut hash as *mut sgx_sha256_hash_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
///
/// The rsgx_sha256_slice function performs a standard SHA256 hash over the input data buffer.
///
pub fn rsgx_sha256_slice<T>(src: &[T]) -> SgxResult<sgx_sha256_hash_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut hash = sgx_sha256_hash_t::default();
let ret = unsafe {
sgx_sha256_msg(
src.as_ptr() as *const u8,
size as u32,
&mut hash as *mut sgx_sha256_hash_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
fn rsgx_sha256_init(sha_handle: &mut sgx_sha_state_handle_t) -> sgx_status_t {
unsafe { sgx_sha256_init(sha_handle as *mut sgx_sha_state_handle_t) }
}
fn rsgx_sha256_update_msg<T>(src: &T, sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_sha256_update(src as *const _ as *const u8, size as u32, sha_handle) }
}
fn rsgx_sha256_update_slice<T>(src: &[T], sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_sha256_update(src.as_ptr() as *const u8, size as u32, sha_handle) }
}
fn rsgx_sha256_get_hash(
sha_handle: sgx_sha_state_handle_t,
hash: &mut sgx_sha256_hash_t,
) -> sgx_status_t {
unsafe { sgx_sha256_get_hash(sha_handle, hash as *mut sgx_sha256_hash_t) }
}
fn rsgx_sha256_close(sha_handle: sgx_sha_state_handle_t) -> sgx_status_t {
unsafe { sgx_sha256_close(sha_handle) }
}
pub fn rsgx_sha1_msg<T>(src: &T) -> SgxResult<sgx_sha1_hash_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut hash = sgx_sha1_hash_t::default();
let ret = unsafe {
sgx_sha1_msg(
src as *const _ as *const u8,
size as u32,
&mut hash as *mut sgx_sha1_hash_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
pub fn rsgx_sha1_slice<T>(src: &[T]) -> SgxResult<sgx_sha1_hash_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut hash = sgx_sha1_hash_t::default();
let ret = unsafe {
sgx_sha1_msg(
src.as_ptr() as *const u8,
size as u32,
&mut hash as *mut sgx_sha1_hash_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
fn rsgx_sha1_init(sha_handle: &mut sgx_sha_state_handle_t) -> sgx_status_t {
unsafe { sgx_sha1_init(sha_handle as *mut sgx_sha_state_handle_t) }
}
fn rsgx_sha1_update_msg<T>(src: &T, sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_sha1_update(src as *const _ as *const u8, size as u32, sha_handle) }
}
fn rsgx_sha1_update_slice<T>(src: &[T], sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_sha1_update(src.as_ptr() as *const u8, size as u32, sha_handle) }
}
fn rsgx_sha1_get_hash(
sha_handle: sgx_sha_state_handle_t,
hash: &mut sgx_sha1_hash_t,
) -> sgx_status_t {
unsafe { sgx_sha1_get_hash(sha_handle, hash as *mut sgx_sha1_hash_t) }
}
fn rsgx_sha1_close(sha_handle: sgx_sha_state_handle_t) -> sgx_status_t {
unsafe { sgx_sha1_close(sha_handle) }
}
///
/// SHA algorithm context state.
///
/// This is a handle to the context state used by the cryptography library to perform an iterative SHA256 hash.
/// The algorithm stores the intermediate results of performing the hash calculation over data sets.
///
pub struct SgxShaHandle {
handle: RefCell<sgx_sha_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxShaHandle {
///
/// Constructs a new, empty SgxShaHandle.
///
pub fn new() -> SgxShaHandle {
SgxShaHandle {
handle: RefCell::new(ptr::null_mut() as sgx_sha_state_handle_t),
initflag: Cell::new(false),
}
}
///
/// init returns an allocated and initialized SHA algorithm context state.
///
/// This should be part of the Init, Update … Update, Final process when the SHA hash is to be performed
/// over multiple datasets. If a complete dataset is available, the recommend call is rsgx_sha256_msg to
/// perform the hash in a single call.
///
/// # Description
///
/// Calling init is the first set in performing a SHA256 hash over multiple datasets. The caller does not
/// allocate memory for the SHA256 state that this function returns. The state is specific to the implementation
/// of the cryptography library; thus the allocation is performed by the library itself. If the hash over the
/// desired datasets is completed or any error occurs during the hash calculation process, sgx_sha256_close should
/// be called to free the state allocated by this algorithm.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The SHA256 state is not initialized properly due to an internal cryptography library failure.
///
pub fn init(&self) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_sha256_init(self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
///
/// update_msg performs a SHA256 hash over the input dataset provided.
///
/// This function supports an iterative calculation of the hash over multiple datasets where the
/// sha_handle contains the intermediate results of the hash calculation over previous datasets.
///
/// # Description
///
/// This function should be used as part of a SHA256 calculation over multiple datasets.
/// If a SHA256 hash is needed over a single data set, function rsgx_sha256_msg should be used instead.
/// Prior to calling this function on the first dataset, the init function must be called first to allocate
/// and initialize the SHA256 state structure which will hold intermediate hash results over earlier datasets.
/// The function get_hash should be used to obtain the hash after the final dataset has been processed
/// by this function.
///
/// # Parameters
///
/// **src**
///
/// A pointer to the input data stream to be hashed.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The SHA256 state is not initialized.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred while performing the SHA256 hash calculation.
///
pub fn update_msg<T>(&self, src: &T) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_sha256_update_msg(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// update_slice performs a SHA256 hash over the input dataset provided.
///
pub fn update_slice<T>(&self, src: &[T]) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_sha256_update_slice(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// get_hash obtains the SHA256 hash after the final dataset has been processed.
///
/// # Description
///
/// This function returns the hash after performing the SHA256 calculation over one or more datasets
/// using the update function.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The 256-bit hash that has been SHA256 calculated
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The SHA256 state is not initialized.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The SHA256 state passed in is likely problematic causing an internal cryptography library failure.
///
pub fn get_hash(&self) -> SgxResult<sgx_sha256_hash_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut hash = sgx_sha256_hash_t::default();
let ret = rsgx_sha256_get_hash(*self.handle.borrow(), &mut hash);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
///
/// close cleans up and deallocates the SHA256 state that was allocated in function init.
///
/// # Description
///
/// Calling close is the last step after performing a SHA256 hash over multiple datasets.
/// The caller uses this function to deallocate memory used to store the SHA256 calculation state.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The input handle is invalid.
///
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_sha256_close(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxShaHandle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxShaHandle {
///
/// drop cleans up and deallocates the SHA256 state that was allocated in function init.
///
fn drop(&mut self) {
let _ = self.close();
}
}
pub struct SgxSha1Handle {
handle: RefCell<sgx_sha_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxSha1Handle {
pub fn new() -> SgxSha1Handle {
SgxSha1Handle {
handle: RefCell::new(ptr::null_mut() as sgx_sha_state_handle_t),
initflag: Cell::new(false),
}
}
pub fn init(&self) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_sha1_init(self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
pub fn update_msg<T>(&self, src: &T) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_sha1_update_msg(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn update_slice<T>(&self, src: &[T]) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_sha1_update_slice(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn get_hash(&self) -> SgxResult<sgx_sha1_hash_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut hash = sgx_sha1_hash_t::default();
let ret = rsgx_sha1_get_hash(*self.handle.borrow(), &mut hash);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_sha1_close(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxSha1Handle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxSha1Handle {
///
/// drop cleans up and deallocates the SHA256 state that was allocated in function init.
///
fn drop(&mut self) {
let _ = self.close();
}
}
///
/// rsgx_rijndael128GCM_encrypt performs a Rijndael AES-GCM encryption operation.
///
/// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
///
/// # Description
///
/// The Galois/Counter Mode (GCM) is a mode of operation of the AES algorithm.
/// GCM [NIST SP 800-38D] uses a variation of the counter mode of operation for
/// encryption. GCM assures authenticity of the confidential data (of up to about
/// 64 GB per invocation) using a universal hash function defined over a binary
/// finite field (the Galois field).
///
/// GCM can also provide authentication assurance for additional data (of practically
/// unlimited length per invocation) that is not encrypted. GCM provides
/// stronger authentication assurance than a (non-cryptographic) checksum or
/// error detecting code. In particular, GCM can detect both accidental modifications
/// of the data and intentional, unauthorized modifications.
///
/// It is recommended that the source and destination data buffers are allocated
/// within the enclave. The AAD buffer could be allocated within or outside
/// enclave memory. The use of AAD data buffer could be information identifying
/// the encrypted data since it will remain in clear text.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the AES-GCM encryption operation. The size must be 128 bits.
///
/// **src**
///
/// A pointer to the input data stream to be encrypted. Buffer content could be empty if there is AAD text.
///
/// **iv**
///
/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended
/// IV size is 96 bits (12 bytes).
///
/// **aad**
///
/// A pointer to an optional additional authentication data buffer which is used in the GCM MAC calculation.
/// The data in this buffer will not be encrypted. The field is optional and content could be empty.
///
/// **dst**
///
/// A pointer to the output encrypted data buffer. This buffer should be allocated by the calling code.
///
/// **mac**
///
/// This is the output GCM MAC performed over the input data buffer (data to be encrypted) as well as
/// the additional authentication data (this is optional data). The calling code should allocate this buffer.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// If both source buffer and AAD buffer content are empty.
///
/// If IV Length is not equal to 12 (bytes).
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn rsgx_rijndael128GCM_encrypt(
key: &sgx_aes_gcm_128bit_key_t,
src: &[u8],
iv: &[u8],
aad: &[u8],
dst: &mut [u8],
mac: &mut sgx_aes_gcm_128bit_tag_t,
) -> SgxError {
let src_len = src.len();
if src_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let iv_len = iv.len();
if iv_len != SGX_AESGCM_IV_SIZE {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let aad_len = aad.len();
if aad_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let dst_len = dst.len();
if dst_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if dst_len < src_len {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
let p_aad = if aad_len != 0 {
aad.as_ptr()
} else {
ptr::null()
};
let (p_src, p_dst) = if src_len != 0 {
(src.as_ptr(), dst.as_mut_ptr())
} else {
(ptr::null(), ptr::null_mut())
};
sgx_rijndael128GCM_encrypt(
key as *const sgx_aes_gcm_128bit_key_t,
p_src,
src_len as u32,
p_dst,
iv.as_ptr(),
iv_len as u32,
p_aad,
aad_len as u32,
mac as *mut sgx_aes_gcm_128bit_tag_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// rsgx_rijndael128GCM_decrypt performs a Rijndael AES-GCM decryption operation.
///
/// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
///
/// # Description
///
/// The Galois/Counter Mode (GCM) is a mode of operation of the AES algorithm.
/// GCM [NIST SP 800-38D] uses a variation of the counter mode of operation for
/// encryption. GCM assures authenticity of the confidential data (of up to about
/// 64 GB per invocation) using a universal hash function defined over a binary
/// finite field (the Galois field).
///
/// GCM can also provide authentication assurance for additional data (of practically
/// unlimited length per invocation) that is not encrypted. GCM provides
/// stronger authentication assurance than a (non-cryptographic) checksum or
/// error detecting code. In particular, GCM can detect both accidental modifications
/// of the data and intentional, unauthorized modifications.
///
/// It is recommended that the destination data buffer is allocated within the
/// enclave. The AAD buffer could be allocated within or outside enclave memory.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the AES-GCM decryption operation. The size must be 128 bits.
///
/// **src**
///
/// A pointer to the input data stream to be decrypted. Buffer content could be empty if there is AAD text.
///
/// **iv**
///
/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended
/// IV size is 96 bits (12 bytes).
///
/// **aad**
///
/// A pointer to an optional additional authentication data buffer which is provided for the GCM MAC calculation
/// when encrypting. The data in this buffer was not encrypted. The field is optional and content could be empty.
///
/// **mac**
///
/// This is the GCM MAC that was performed over the input data buffer (data to be encrypted) as well as
/// the additional authentication data (this is optional data) during the encryption process (call to
/// rsgx_rijndael128GCM_encrypt).
///
/// **dst**
///
/// A pointer to the output decrypted data buffer. This buffer should be allocated by the calling code.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// If both source buffer and AAD buffer content are empty.
///
/// If IV Length is not equal to 12 (bytes).
///
/// **SGX_ERROR_MAC_MISMATCH**
///
/// The input MAC does not match the MAC calculated.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn rsgx_rijndael128GCM_decrypt(
key: &sgx_aes_gcm_128bit_key_t,
src: &[u8],
iv: &[u8],
aad: &[u8],
mac: &sgx_aes_gcm_128bit_tag_t,
dst: &mut [u8],
) -> SgxError {
let src_len = src.len();
if src_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let iv_len = iv.len();
if iv_len != SGX_AESGCM_IV_SIZE {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let aad_len = aad.len();
if aad_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let dst_len = dst.len();
if dst_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if dst_len < src_len {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
let p_aad = if !aad.is_empty() {
aad.as_ptr()
} else {
ptr::null()
};
let (p_src, p_dst) = if src_len != 0 {
(src.as_ptr(), dst.as_mut_ptr())
} else {
(ptr::null(), ptr::null_mut())
};
sgx_rijndael128GCM_decrypt(
key as *const sgx_aes_gcm_128bit_key_t,
p_src,
src_len as u32,
p_dst,
iv.as_ptr(),
iv_len as u32,
p_aad,
aad_len as u32,
mac as *const sgx_aes_gcm_128bit_tag_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// The rsgx_rijndael128_cmac_msg function performs a standard 128bit CMAC hash over the input data buffer.
///
/// # Description
///
/// The rsgx_rijndael128_cmac_msg function performs a standard CMAC hash over the input data buffer.
/// Only a 128-bit version of the CMAC hash is supported.
///
/// The function should be used if the complete input data stream is available.
/// Otherwise, the Init, Update… Update, Final procedure should be used to compute
/// a CMAC hash over multiple input data sets.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the CMAC hash operation. The size must be 128 bits.
///
/// **src**
///
/// A pointer to the input data stream to be hashed.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The 128-bit hash that has been CMAC calculated
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn rsgx_rijndael128_cmac_msg<T>(
key: &sgx_cmac_128bit_key_t,
src: &T,
) -> SgxResult<sgx_cmac_128bit_tag_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut mac = sgx_cmac_128bit_tag_t::default();
let ret = unsafe {
sgx_rijndael128_cmac_msg(
key as *const sgx_cmac_128bit_key_t,
src as *const _ as *const u8,
size as u32,
&mut mac as *mut sgx_cmac_128bit_tag_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(mac),
_ => Err(ret),
}
}
///
/// The rsgx_rijndael128_cmac_slice function performs a standard 128bit CMAC hash over the input data buffer.
///
pub fn rsgx_rijndael128_cmac_slice<T>(
key: &sgx_cmac_128bit_key_t,
src: &[T],
) -> SgxResult<sgx_cmac_128bit_tag_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut mac = sgx_cmac_128bit_tag_t::default();
let ret = unsafe {
sgx_rijndael128_cmac_msg(
key as *const sgx_cmac_128bit_key_t,
src.as_ptr() as *const u8,
size as u32,
&mut mac as *mut sgx_cmac_128bit_tag_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(mac),
_ => Err(ret),
}
}
fn rsgx_cmac128_init(
key: &sgx_cmac_128bit_key_t,
cmac_handle: &mut sgx_cmac_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_cmac128_init(
key as *const sgx_cmac_128bit_key_t,
cmac_handle as *mut sgx_cmac_state_handle_t,
)
}
}
fn rsgx_cmac128_update_msg<T>(src: &T, cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_cmac128_update(src as *const _ as *const u8, size as u32, cmac_handle) }
}
fn rsgx_cmac128_update_slice<T>(src: &[T], cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_cmac128_update(
src.as_ptr() as *const _ as *const u8,
size as u32,
cmac_handle,
)
}
}
fn rsgx_cmac128_final(
cmac_handle: sgx_cmac_state_handle_t,
hash: &mut sgx_cmac_128bit_tag_t,
) -> sgx_status_t {
unsafe { sgx_cmac128_final(cmac_handle, hash as *mut sgx_cmac_128bit_tag_t) }
}
fn rsgx_cmac128_close(cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t {
unsafe { sgx_cmac128_close(cmac_handle) }
}
///
/// CMAC algorithm context state.
///
/// This is a handle to the context state used by the cryptography library to perform an
/// iterative CMAC 128-bit hash. The algorithm stores the intermediate results of performing
/// the hash calculation over data sets.
///
pub struct SgxCmacHandle {
handle: RefCell<sgx_cmac_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxCmacHandle {
///
/// Constructs a new, empty SgxCmacHandle.
///
pub fn new() -> SgxCmacHandle {
SgxCmacHandle {
handle: RefCell::new(ptr::null_mut() as sgx_cmac_state_handle_t),
initflag: Cell::new(false),
}
}
///
/// init returns an allocated and initialized CMAC algorithm context state.
///
/// This should be part of the Init, Update … Update, Final process when the CMAC hash is to be
/// performed over multiple datasets. If a complete dataset is available, the recommended call
/// is rsgx_rijndael128_cmac_msg to perform the hash in a single call.
///
/// # Description
///
/// Calling init is the first set in performing a CMAC 128-bit hash over multiple datasets.
/// The caller does not allocate memory for the CMAC state that this function returns.
/// The state is specific to the implementation of the cryptography library and thus the
/// allocation is performed by the library itself. If the hash over the desired datasets is
/// completed or any error occurs during the hash calculation process, sgx_cmac128_close should
/// be called to free the state allocated by this algorithm.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the CMAC hash operation. The size must be 128 bits.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn init(&self, key: &sgx_cmac_128bit_key_t) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_cmac128_init(key, self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
///
/// update_msg performs a CMAC 128-bit hash over the input dataset provided.
///
/// This function supports an iterative calculation of the hash over multiple datasets where the
/// cmac_handle contains the intermediate results of the hash calculation over previous datasets.
///
/// # Description
///
/// This function should be used as part of a CMAC 128-bit hash calculation over
/// multiple datasets. If a CMAC hash is needed over a single data set, function
/// rsgx_rijndael128_cmac128_msg should be used instead. Prior to calling
/// this function on the first dataset, the init function must be called first to
/// allocate and initialize the CMAC state structure which will hold intermediate
/// hash results over earlier datasets. The function get_hash should be used
/// to obtain the hash after the final dataset has been processed by this function.
///
/// # Parameters
///
/// **src**
///
/// A pointer to the input data stream to be hashed.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The CMAC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred while performing the CMAC hash calculation.
///
pub fn update_msg<T>(&self, src: &T) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_cmac128_update_msg(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// update_slice performs a CMAC 128-bit hash over the input dataset provided.
///
pub fn update_slice<T>(&self, src: &[T]) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_cmac128_update_slice(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// get_hash obtains the CMAC 128-bit hash after the final dataset has been processed.
///
/// # Description
///
/// This function returns the hash after performing the CMAC 128-bit hash calculation
/// over one or more datasets using the update function.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The 128-bit hash that has been CMAC calculated
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The CMAC state is not initialized.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The CMAC state passed in is likely problematic causing an internal cryptography library failure.
///
pub fn get_hash(&self) -> SgxResult<sgx_cmac_128bit_tag_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut hash = sgx_cmac_128bit_tag_t::default();
let ret = rsgx_cmac128_final(*self.handle.borrow(), &mut hash);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
///
/// close cleans up and deallocates the CMAC algorithm context state that was allocated in function init.
///
/// # Description
///
/// Calling close is the last step after performing a CMAC hash over multiple datasets.
/// The caller uses this function to deallocate memory used for storing the CMAC algorithm context state.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The input handle is invalid.
///
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_cmac128_close(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxCmacHandle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxCmacHandle {
///
/// drop cleans up and deallocates the CMAC algorithm context state that was allocated in function init.
///
fn drop(&mut self) {
let _ = self.close();
}
}
pub fn rsgx_hmac_sha256_msg<T>(
key: &sgx_hmac_256bit_key_t,
src: &T,
) -> SgxResult<sgx_hmac_256bit_tag_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut mac = sgx_hmac_256bit_tag_t::default();
let ret = unsafe {
sgx_hmac_sha256_msg(
src as *const _ as *const u8,
size as i32,
key as *const u8,
SGX_HMAC256_KEY_SIZE as i32,
&mut mac as *mut sgx_hmac_256bit_tag_t as *mut u8,
SGX_HMAC256_MAC_SIZE as i32,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(mac),
_ => Err(ret),
}
}
pub fn rsgx_hmac_sha256_slice<T>(
key: &sgx_hmac_256bit_key_t,
src: &[T],
) -> SgxResult<sgx_hmac_256bit_tag_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut mac = sgx_hmac_256bit_tag_t::default();
let ret = unsafe {
sgx_hmac_sha256_msg(
src.as_ptr() as *const u8,
size as i32,
key as *const u8,
SGX_HMAC256_KEY_SIZE as i32,
&mut mac as *mut sgx_hmac_256bit_tag_t as *mut u8,
SGX_HMAC256_MAC_SIZE as i32,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(mac),
_ => Err(ret),
}
}
fn rsgx_hmac256_init(
key: &sgx_hmac_256bit_key_t,
hmac_handle: &mut sgx_hmac_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_hmac256_init(
key as *const sgx_hmac_256bit_key_t as *const u8,
SGX_HMAC256_KEY_SIZE as i32,
hmac_handle as *mut sgx_hmac_state_handle_t,
)
}
}
fn rsgx_hmac256_update_msg<T>(src: &T, hmac_handle: sgx_hmac_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_hmac256_update(src as *const _ as *const u8, size as i32, hmac_handle) }
}
fn rsgx_hmac256_update_slice<T>(src: &[T], hmac_handle: sgx_hmac_state_handle_t) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(src);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_hmac256_update(
src.as_ptr() as *const _ as *const u8,
size as i32,
hmac_handle,
)
}
}
fn rsgx_hmac256_final(
hmac_handle: sgx_hmac_state_handle_t,
hash: &mut sgx_hmac_256bit_tag_t,
) -> sgx_status_t {
unsafe {
sgx_hmac256_final(
hash as *mut sgx_hmac_256bit_tag_t as *mut u8,
SGX_HMAC256_MAC_SIZE as i32,
hmac_handle,
)
}
}
fn rsgx_hmac256_close(hmac_handle: sgx_hmac_state_handle_t) -> sgx_status_t {
unsafe { sgx_hmac256_close(hmac_handle) }
}
pub struct SgxHmacHandle {
handle: RefCell<sgx_hmac_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxHmacHandle {
pub fn new() -> SgxHmacHandle {
SgxHmacHandle {
handle: RefCell::new(ptr::null_mut() as sgx_hmac_state_handle_t),
initflag: Cell::new(false),
}
}
pub fn init(&self, key: &sgx_hmac_256bit_key_t) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_hmac256_init(key, self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
pub fn update_msg<T>(&self, src: &T) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_hmac256_update_msg(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn update_slice<T>(&self, src: &[T]) -> SgxError
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_hmac256_update_slice(src, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn get_hash(&self) -> SgxResult<sgx_hmac_256bit_tag_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut hash = sgx_hmac_256bit_tag_t::default();
let ret = rsgx_hmac256_final(*self.handle.borrow(), &mut hash);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(hash),
_ => Err(ret),
}
}
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_hmac256_close(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxHmacHandle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxHmacHandle {
fn drop(&mut self) {
let _ = self.close();
}
}
pub const SGX_AESCTR_CTR_SIZE: size_t = 16;
pub type sgx_aes_ctr_128bit_ctr_t = [uint8_t; SGX_AESCTR_CTR_SIZE];
///
/// rsgx_aes_ctr_encrypt performs a Rijndael AES-CTR encryption operation.
///
/// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
///
/// # Description
///
/// This function encrypts the input data stream of a variable length according to
/// the CTR mode as specified in [NIST SP 800-38A]. The counter can be thought
/// of as an IV which increments on successive encryption or decryption calls. For
/// a given dataset or data stream, the incremented counter block should be used
/// on successive calls of the encryption process for that given stream. However,
/// for new or different datasets/streams, the same counter should not be reused,
/// instead initialize the counter for the new data set.
///
/// It is recommended that the source, destination and counter data buffers are
/// allocated within the enclave.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the AES-CTR encryption operation. The size must be 128 bits.
///
/// **src**
///
/// A pointer to the input data stream to be encrypted.
///
/// **ctr**
///
/// A pointer to the initialization vector to be used in the AES-CTR calculation.
///
/// **ctr_inc_bits**
///
/// Specifies the number of bits in the counter to be incremented.
///
/// **dst**
///
/// A pointer to the output encrypted data buffer. This buffer should be allocated by the calling code.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn rsgx_aes_ctr_encrypt(
key: &sgx_aes_ctr_128bit_key_t,
src: &[u8],
ctr: &sgx_aes_ctr_128bit_ctr_t,
ctr_inc_bits: u32,
dst: &mut [u8],
) -> SgxError {
let src_len = src.len();
if src_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if src_len < 1 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let dst_len = dst.len();
if dst_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if dst_len < src_len {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
sgx_aes_ctr_encrypt(
key as *const sgx_aes_ctr_128bit_key_t,
src.as_ptr(),
src_len as u32,
ctr as *const sgx_aes_ctr_128bit_ctr_t as *const u8,
ctr_inc_bits,
dst.as_mut_ptr(),
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// rsgx_aes_ctr_decrypt performs a Rijndael AES-CTR decryption operation.
///
/// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
///
/// # Description
///
/// This function decrypts the input data stream of a variable length according to
/// the CTR mode as specified in [NIST SP 800-38A]. The counter can be thought
/// of as an IV which increments on successive encryption or decryption calls. For
/// a given dataset or data stream, the incremented counter block should be used
/// on successive calls of the decryption process for that given stream. However,
/// for new or different datasets/streams, the same counter should not be reused,
/// instead initialize the counter for the new data set.
///
/// It is recommended that the source, destination and counter data buffers are
/// allocated within the enclave.
///
/// # Parameters
///
/// **key**
///
/// A pointer to key to be used in the AES-CTR encryption operation. The size must be 128 bits.
///
/// **src**
///
/// A pointer to the input data stream to be decrypted.
///
/// **ctr**
///
/// A pointer to the initialization vector to be used in the AES-CTR calculation.
///
/// **ctr_inc_bits**
///
/// Specifies the number of bits in the counter to be incremented.
///
/// **dst**
///
/// A pointer to the output decrypted data buffer. This buffer should be allocated by the calling code.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn rsgx_aes_ctr_decrypt(
key: &sgx_aes_ctr_128bit_key_t,
src: &[u8],
ctr: &sgx_aes_ctr_128bit_ctr_t,
ctr_inc_bits: u32,
dst: &mut [u8],
) -> SgxError {
let src_len = src.len();
if src_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if src_len < 1 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let dst_len = dst.len();
if dst_len > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if dst_len < src_len {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
sgx_aes_ctr_decrypt(
key as *const sgx_aes_ctr_128bit_key_t,
src.as_ptr(),
src.len() as u32,
ctr as *const sgx_aes_ctr_128bit_ctr_t as *const u8,
ctr_inc_bits,
dst.as_mut_ptr(),
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
fn rsgx_ecc256_open_context(ecc_handle: &mut sgx_ecc_state_handle_t) -> sgx_status_t {
unsafe { sgx_ecc256_open_context(ecc_handle as *mut _ as *mut sgx_ecc_state_handle_t) }
}
fn rsgx_ecc256_close_context(ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
unsafe { sgx_ecc256_close_context(ecc_handle) }
}
fn rsgx_ecc256_create_key_pair(
private: &mut sgx_ec256_private_t,
public: &mut sgx_ec256_public_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_ecc256_create_key_pair(
private as *mut sgx_ec256_private_t,
public as *mut sgx_ec256_public_t,
ecc_handle,
)
}
}
fn rsgx_ecc256_check_point(
point: &sgx_ec256_public_t,
ecc_handle: sgx_ecc_state_handle_t,
valid: &mut i32,
) -> sgx_status_t {
unsafe {
sgx_ecc256_check_point(
point as *const sgx_ec256_public_t,
ecc_handle,
valid as *mut i32,
)
}
}
fn rsgx_ecc256_compute_shared_dhkey(
private_b: &sgx_ec256_private_t,
public_ga: &sgx_ec256_public_t,
shared_key: &mut sgx_ec256_dh_shared_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_ecc256_compute_shared_dhkey(
private_b as *const sgx_ec256_private_t,
public_ga as *const sgx_ec256_public_t,
shared_key as *mut sgx_ec256_dh_shared_t,
ecc_handle,
)
}
}
/* delete (intel sgx sdk 2.0)
fn rsgx_ecc256_compute_shared_dhkey512(
private_b: &sgx_ec256_private_t,
public_ga: &sgx_ec256_public_t,
shared_key: &mut sgx_ec256_dh_shared512_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_ecc256_compute_shared_dhkey512(
private_b as *const _ as *mut sgx_ec256_private_t,
public_ga as *const _ as *mut sgx_ec256_public_t,
shared_key as *mut sgx_ec256_dh_shared512_t,
ecc_handle,
)
}
}
*/
fn rsgx_ecdsa_sign_msg<T>(
data: &T,
private: &sgx_ec256_private_t,
signature: &mut sgx_ec256_signature_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_ecdsa_sign(
data as *const _ as *const u8,
size as u32,
private as *const sgx_ec256_private_t,
signature as *mut sgx_ec256_signature_t,
ecc_handle,
)
}
}
fn rsgx_ecdsa_sign_slice<T>(
data: &[T],
private: &sgx_ec256_private_t,
signature: &mut sgx_ec256_signature_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(data);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_ecdsa_sign(
data.as_ptr() as *const _ as *const u8,
size as u32,
private as *const sgx_ec256_private_t,
signature as *mut sgx_ec256_signature_t,
ecc_handle,
)
}
}
fn rsgx_ecdsa_verify_msg<T>(
data: &T,
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
result: &mut sgx_generic_ecresult_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
let mut verify: u8 = 0;
let ret = sgx_ecdsa_verify(
data as *const _ as *const u8,
size as u32,
public as *const sgx_ec256_public_t,
signature as *const sgx_ec256_signature_t,
&mut verify as *mut u8,
ecc_handle,
);
match ret {
sgx_status_t::SGX_SUCCESS => {
let ecresult = sgx_generic_ecresult_t::from_repr(u32::from(verify));
*result = ecresult.unwrap_or(sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE);
}
_ => {
*result = sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE;
}
};
ret
}
}
fn rsgx_ecdsa_verify_slice<T>(
data: &[T],
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
result: &mut sgx_generic_ecresult_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(data);
if size == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if size > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
let mut verify: u8 = 0;
let ret = sgx_ecdsa_verify(
data.as_ptr() as *const _ as *const u8,
size as u32,
public as *const sgx_ec256_public_t,
signature as *const sgx_ec256_signature_t,
&mut verify as *mut u8,
ecc_handle,
);
match ret {
sgx_status_t::SGX_SUCCESS => {
let ecresult = sgx_generic_ecresult_t::from_repr(u32::from(verify));
*result = ecresult.unwrap_or(sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE);
}
_ => {
*result = sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE;
}
};
ret
}
}
fn rsgx_ecdsa_verify_hash(
hash: &sgx_sha256_hash_t,
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
result: &mut sgx_generic_ecresult_t,
ecc_handle: sgx_ecc_state_handle_t,
) -> sgx_status_t {
unsafe {
let mut verify: u8 = 0;
let ret = sgx_ecdsa_verify_hash(
hash as *const sgx_sha256_hash_t as *const u8,
public as *const sgx_ec256_public_t,
signature as *const sgx_ec256_signature_t,
&mut verify as *mut u8,
ecc_handle,
);
match ret {
sgx_status_t::SGX_SUCCESS => {
let ecresult = sgx_generic_ecresult_t::from_repr(u32::from(verify));
*result = ecresult.unwrap_or(sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE);
}
_ => {
*result = sgx_generic_ecresult_t::SGX_EC_INVALID_SIGNATURE;
}
};
ret
}
}
///
/// ECC GF(p) context state.
///
/// This is a handle to the ECC GF(p) context state allocated and initialized used to perform
/// elliptic curve cryptosystem standard functions. The algorithm stores the intermediate results
/// of calculations performed using this context.
///
pub struct SgxEccHandle {
handle: RefCell<sgx_ecc_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxEccHandle {
///
/// Constructs a new, empty SgxEccHandle.
///
pub fn new() -> SgxEccHandle {
SgxEccHandle {
handle: RefCell::new(ptr::null_mut() as sgx_ecc_state_handle_t),
initflag: Cell::new(false),
}
}
///
/// open returns an allocated and initialized context for the elliptic curve cryptosystem
/// over a prime finite field, GF(p).
///
/// This context must be created prior to calling create_key_pair or compute_shared_dhkey.
/// When the calling code has completed its set of ECC operations, close should be called to
/// cleanup and deallocate the ECC context.
///
/// # Description
///
/// open is utilized to allocate and initialize a 256-bit
/// GF(p) cryptographic system. The caller does not allocate memory for the ECC
/// state that this function returns. The state is specific to the implementation of
/// the cryptography library and thus the allocation is performed by the library
/// itself. If the ECC cryptographic function using this cryptographic system is completed
/// or any error occurs, close should be called to free the state allocated by this algorithm.
///
/// Public key cryptography successfully allows to solving problems of information
/// safety by enabling trusted communication over insecure channels. Although
/// elliptic curves are well studied as a branch of mathematics, an interest to the
/// cryptographic schemes based on elliptic curves is constantly rising due to the
/// advantages that the elliptic curve algorithms provide in the wireless communications:
/// shorter processing time and key length.
///
/// Elliptic curve cryptosystems (ECCs) implement a different way of creating public
/// keys. As elliptic curve calculation is based on the addition of the rational
/// points in the (x,y) plane and it is difficult to solve a discrete logarithm from
/// these points, a higher level of safety is achieved through the cryptographic
/// schemes that use the elliptic curves. The cryptographic systems that encrypt
/// messages by using the properties of elliptic curves are hard to attack due to
/// the extreme complexity of deciphering the private key.
///
/// Using of elliptic curves allows shorter public key length and encourages cryptographers
/// to create cryptosystems with the same or higher encryption
/// strength as the RSA or DSA cryptosystems. Because of the relatively short key
/// length, ECCs do encryption and decryption faster on the hardware that
/// requires less computation processing volumes.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The ECC context state was not initialized properly due to an internal cryptography library failure.
///
pub fn open(&self) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_ecc256_open_context(self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
///
/// create_key_pair generates a private/public key pair on the ECC curve for the given
/// cryptographic system.
///
/// open must be called to allocate and initialize the ECC context prior to making this call.
///
/// # Description
///
/// This function populates private/public key pair. The calling code allocates
/// memory for the private and public key pointers to be populated. The function
/// generates a private key p_private and computes a public key p_public of
/// the elliptic cryptosystem over a finite field GF(p).
///
/// The private key p_private is a number that lies in the range of [1, n-1]
/// where n is the order of the elliptic curve base point.
/// The public key p_public is an elliptic curve point such that p_public =
/// p_private *G, where G is the base point of the elliptic curve.
/// The context of the point p_public as an elliptic curve point must be created
/// by using the function open.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// **sgx_ec256_private_t**
///
/// The private key which is a number that lies in the range of [1, n-1] where n is the order
/// of the elliptic curve base point.
///
/// **sgx_ec256_public_t**
///
/// The public key which is an elliptic curve point such that:
///
/// public key = private key * G, where G is the base point of the elliptic curve.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The ECC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The key creation process failed due to an internal cryptography library failure.
///
pub fn create_key_pair(&self) -> SgxResult<(sgx_ec256_private_t, sgx_ec256_public_t)> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut private = sgx_ec256_private_t::default();
let mut public = sgx_ec256_public_t::default();
let ret = rsgx_ecc256_create_key_pair(&mut private, &mut public, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok((private, public)),
_ => Err(ret),
}
}
///
/// check_point checks whether the input point is a valid point on the ECC curve for the given cryptographic system.
///
/// open context must be called to allocate and initialize the ECC context prior to making this call.
///
/// # Description
///
/// check_point validates whether the input point is a valid point on the ECC curve for the given cryptographic system.
///
/// # Parameters
///
/// **point**
///
/// A pointer to the point to perform validity check on.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// **true**
///
/// The input point is valid
///
/// **false**
///
/// The input point is not valid
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The ECC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// An internal cryptography library failure occurred.
///
pub fn check_point(&self, point: &sgx_ec256_public_t) -> SgxResult<bool> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut valid: i32 = 0;
let ret = rsgx_ecc256_check_point(point, *self.handle.borrow(), &mut valid);
match ret {
sgx_status_t::SGX_SUCCESS => {
if valid > 0 {
Ok(true)
} else {
Ok(false)
}
}
_ => Err(ret),
}
}
///
/// compute_shared_dhkey generates a secret key shared between two participants of the cryptosystem.
///
/// # Description
///
/// This function computes the Diffie-Hellman shared key based on the enclave’s
/// own (local) private key and remote enclave’s public Ga Key.
///
/// The function computes a secret number sharedKey, which is a secret key
/// shared between two participants of the cryptosystem.
///
/// In cryptography, metasyntactic names such as Alice as Bob are normally used
/// as examples and in discussions and stand for participant A and participant B.
///
/// Both participants (Alice and Bob) use the cryptosystem for receiving a common
/// secret point on the elliptic curve called a secret key (sharedKey). To
/// receive a secret key, participants apply the Diffie-Hellman key-agreement
/// scheme involving public key exchange. The value of the secret key entirely
/// depends on participants.
///
/// According to the scheme, Alice and Bob perform the following operations:
///
/// 1. Alice calculates her own public key pubKeyA by using her private key
/// privKeyA: pubKeyA = privKeyA * G, where G is the base point of the
/// elliptic curve.
///
/// 2. Alice passes the public key to Bob.
///
/// 3. Bob calculates his own public key pubKeyB by using his private key
/// privKeyB: pubKeyB = privKeyB * G, where G is a base point of the elliptic curve.
///
/// 4. Bob passes the public key to Alice.
///
/// 5. Alice gets Bob's public key and calculates the secret point shareKeyA. When
/// calculating, she uses her own private key and Bob's public key and applies the
/// following formula:
///
/// shareKeyA = privKeyA * pubKeyB = privKeyA * privKeyB * G.
///
/// 6. Bob gets Alice's public key and calculates the secret point shareKeyB. When
/// calculating, he uses his own private key and Alice's public key and applies the
/// following formula:
///
/// shareKeyB = privKeyB * pubKeyA = privKeyB * privKeyA * G.
///
/// As the following equation is true privKeyA * privKeyB * G =
/// privKeyB * privKeyA * G, the result of both calculations is the same,
/// that is, the equation shareKeyA = shareKeyB is true. The secret point serves as
/// a secret key.
///
/// Shared secret shareKey is an x-coordinate of the secret point on the elliptic
/// curve. The elliptic curve domain parameters must be hitherto defined by the
/// function: open.
///
/// # Parameters
///
/// **private_b**
///
/// A pointer to the local private key.
///
/// **public_ga**
///
/// A pointer to the remote public key.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The secret key generated by this function which is a common point on the elliptic curve.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The ECC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The key creation process failed due to an internal cryptography library failure.
///
pub fn compute_shared_dhkey(
&self,
private_b: &sgx_ec256_private_t,
public_ga: &sgx_ec256_public_t,
) -> SgxResult<sgx_ec256_dh_shared_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut shared_key = sgx_ec256_dh_shared_t::default();
let ret = rsgx_ecc256_compute_shared_dhkey(
private_b,
public_ga,
&mut shared_key,
*self.handle.borrow(),
);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(shared_key),
_ => Err(ret),
}
}
/* delete (intel sgx sdk 2.0)
pub fn compute_shared_dhkey512(&self, private_b: &sgx_ec256_private_t, public_ga: &sgx_ec256_public_t) -> SgxResult<sgx_ec256_dh_shared512_t> {
if self.initflag.get() == false {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut shared_key = sgx_ec256_dh_shared512_t::default();
let ret = rsgx_ecc256_compute_shared_dhkey512(private_b, public_ga, &mut shared_key, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(shared_key),
_ => Err(ret),
}
}
*/
///
/// ecdsa_sign_msg computes a digital signature with a given private key over an input dataset.
///
/// # Description
///
/// This function computes a digital signature over the input dataset based on the
/// put private key.
///
/// A message digest is a fixed size number derived from the original message
// with an applied hash function over the binary code of the message. (SHA256
/// in this case)
///
/// The signer's private key and the message digest are used to create a signature.
///
/// A digital signature over a message consists of a pair of large numbers, 256-bits
/// each, which the given function computes.
///
/// The scheme used for computing a digital signature is of the ECDSA scheme, an
/// elliptic curve of the DSA scheme.
///
/// The keys can be generated and set up by the function: create_key_pair.
///
/// The elliptic curve domain parameters must be created by function: open.
///
/// # Parameters
///
/// **data**
///
/// A pointer to the data to calculate the signature over.
///
/// **private**
///
/// A pointer to the private key to be used in the calculation of the signature.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The signature generated by this function.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The ECC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The signature generation process failed due to an internal cryptography library failure.
///
pub fn ecdsa_sign_msg<T>(
&self,
data: &T,
private: &sgx_ec256_private_t,
) -> SgxResult<sgx_ec256_signature_t>
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut signature = sgx_ec256_signature_t::default();
let ret = rsgx_ecdsa_sign_msg(data, private, &mut signature, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(signature),
_ => Err(ret),
}
}
///
/// ecdsa_sign_slice computes a digital signature with a given private key over an input dataset.
///
pub fn ecdsa_sign_slice<T>(
&self,
data: &[T],
private: &sgx_ec256_private_t,
) -> SgxResult<sgx_ec256_signature_t>
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut signature = sgx_ec256_signature_t::default();
let ret = rsgx_ecdsa_sign_slice(data, private, &mut signature, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(signature),
_ => Err(ret),
}
}
///
/// ecdsa_verify_msg verifies the input digital signature with a given public key over an input dataset.
///
/// # Description
///
/// This function verifies the signature for the given data set based on the input public key.
///
/// A digital signature over a message consists of a pair of large numbers, 256-bits
/// each, which could be created by function: sgx_ecdsa_sign. The scheme
/// used for computing a digital signature is of the ECDSA scheme, an elliptic
/// curve of the DSA scheme.
///
/// The elliptic curve domain parameters must be created by function: open.
///
/// # Parameters
///
/// **data**
///
/// A pointer to the signed dataset to verify.
///
/// **public**
///
/// A pointer to the public key to be used in the calculation of the signature.
///
/// **signature**
///
/// A pointer to the signature to be verified.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// **true**
///
/// Digital signature is valid.
///
/// **false**
///
/// Digital signature is not valid.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The pointer is invalid.
///
/// **SGX_ERROR_INVALID_STATE**
///
/// The ECC state is not initialized.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The verification process failed due to an internal cryptography library failure.
///
pub fn ecdsa_verify_msg<T>(
&self,
data: &T,
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
) -> SgxResult<bool>
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut result = sgx_generic_ecresult_t::default();
let ret =
rsgx_ecdsa_verify_msg(data, public, signature, &mut result, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => match result {
sgx_generic_ecresult_t::SGX_EC_VALID => Ok(true),
_ => Ok(false),
},
_ => Err(ret),
}
}
///
/// ecdsa_verify_slice verifies the input digital signature with a given public key over an input dataset.
///
pub fn ecdsa_verify_slice<T>(
&self,
data: &[T],
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
) -> SgxResult<bool>
where
T: Copy + ContiguousMemory,
{
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut result = sgx_generic_ecresult_t::default();
let ret =
rsgx_ecdsa_verify_slice(data, public, signature, &mut result, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => match result {
sgx_generic_ecresult_t::SGX_EC_VALID => Ok(true),
_ => Ok(false),
},
_ => Err(ret),
}
}
pub fn ecdsa_verify_hash(
&self,
hash: &sgx_sha256_hash_t,
public: &sgx_ec256_public_t,
signature: &sgx_ec256_signature_t,
) -> SgxResult<bool> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut result = sgx_generic_ecresult_t::default();
let ret =
rsgx_ecdsa_verify_hash(hash, public, signature, &mut result, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => match result {
sgx_generic_ecresult_t::SGX_EC_VALID => Ok(true),
_ => Ok(false),
},
_ => Err(ret),
}
}
///
/// close cleans up and deallocates the ECC 256 GF(p) state that was allocated in function open.
///
/// # Description
///
/// close is used by calling code to deallocate memory used for storing the ECC 256 GF(p) state used
/// in ECC cryptographic calculations.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The input handle is invalid.
///
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_ecc256_close_context(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxEccHandle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxEccHandle {
///
/// close cleans up and deallocates the ECC 256 GF(p) state that was allocated in function open.
///
fn drop(&mut self) {
let _ = self.close();
}
}
///
/// The rsgx_rsa3072_sign_msg computes a digital signature for a given dataset based on RSA 3072 private key.
///
/// # Description
///
/// This function computes a digital signature over the input dataset based on the RSA 3072 private key.
///
/// A message digest is a fixed size number derived from the original message with an applied hash function
/// over the binary code of the message. (SHA256 in this case)
///
/// The signer's private key and the message digest are used to create a signature.
///
/// The scheme used for computing a digital signature is of the RSASSA-PKCS1-v1_5 scheme.
///
/// # Parameters
///
/// **data**
///
/// A pointer to the data to calculate the signature over.
///
/// **key**
///
/// A pointer to the RSA key.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// The signature generated by this function.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The RSA key, data is NULL. Or the data size is 0.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The signature generation process failed due to an internal cryptography library failure.
///
pub fn rsgx_rsa3072_sign_msg<T>(
data: &T,
key: &sgx_rsa3072_key_t,
) -> SgxResult<sgx_rsa3072_signature_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut sign = sgx_rsa3072_signature_t::default();
let ret = unsafe {
sgx_rsa3072_sign(
data as *const _ as *const u8,
size as u32,
key as *const sgx_rsa3072_key_t,
&mut sign as *mut sgx_rsa3072_signature_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(sign),
_ => Err(ret),
}
}
///
/// The rsgx_rsa3072_sign_slice computes a digital signature for a given dataset based on RSA 3072 private key.
///
pub fn rsgx_rsa3072_sign_slice<T>(
data: &[T],
key: &sgx_rsa3072_key_t,
) -> SgxResult<sgx_rsa3072_signature_t>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(data);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut sign = sgx_rsa3072_signature_t::default();
let ret = unsafe {
sgx_rsa3072_sign(
data.as_ptr() as *const _ as *const u8,
size as u32,
key as *const sgx_rsa3072_key_t,
&mut sign as *mut sgx_rsa3072_signature_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(sign),
_ => Err(ret),
}
}
///
/// rsgx_rsa3072_verify_msg verifies the input digital signature for the given data- set based on the RSA 3072 public key.
///
/// # Description
///
/// This function verifies the signature for the given data set based on the input RSA 3072 public key.
///
/// A digital signature over a message is a buffer of 384-bytes, which could be created by function: rsgx_rsa3072_sign.
/// The scheme used for computing a digital signature is of the RSASSA-PKCS1-v1_5 scheme.
///
/// # Parameters
///
/// **data**
///
/// A pointer to the signed dataset to be verified.
///
/// **public**
///
/// A pointer to the public key to be used in the calculation of the signature.
///
/// **signature**
///
/// A pointer to the signature to be verified.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Return value
///
/// **true**
///
/// Digital signature is valid.
///
/// **false**
///
/// Digital signature is not valid.
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// The private key, data is NULL. Or the data size is 0.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// The verification process failed due to an internal cryptography library failure.
///
pub fn rsgx_rsa3072_verify_msg<T>(
data: &T,
public: &sgx_rsa3072_public_key_t,
signature: &sgx_rsa3072_signature_t,
) -> SgxResult<bool>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of::<T>();
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
unsafe {
let mut verify = sgx_rsa_result_t::SGX_RSA_INVALID_SIGNATURE;
let ret = sgx_rsa3072_verify(
data as *const _ as *const u8,
size as u32,
public as *const sgx_rsa3072_public_key_t,
signature as *const sgx_rsa3072_signature_t,
&mut verify as *mut sgx_rsa_result_t,
);
match ret {
sgx_status_t::SGX_SUCCESS => match verify {
sgx_rsa_result_t::SGX_RSA_VALID => Ok(true),
_ => Ok(false),
},
_ => Err(ret),
}
}
}
///
/// rsgx_rsa3072_verify_slice verifies the input digital signature for the given data- set based on the RSA 3072 public key.
///
pub fn rsgx_rsa3072_verify_slice<T>(
data: &[T],
public: &sgx_rsa3072_public_key_t,
signature: &sgx_rsa3072_signature_t,
) -> SgxResult<bool>
where
T: Copy + ContiguousMemory,
{
let size = mem::size_of_val(data);
if size == 0 {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if size > u32::MAX as usize {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
unsafe {
let mut verify = sgx_rsa_result_t::SGX_RSA_INVALID_SIGNATURE;
let ret = sgx_rsa3072_verify(
data.as_ptr() as *const _ as *const u8,
size as u32,
public as *const sgx_rsa3072_public_key_t,
signature as *const sgx_rsa3072_signature_t,
&mut verify as *mut sgx_rsa_result_t,
);
match ret {
sgx_status_t::SGX_SUCCESS => match verify {
sgx_rsa_result_t::SGX_RSA_VALID => Ok(true),
_ => Ok(false),
},
_ => Err(ret),
}
}
}
#[allow(clippy::many_single_char_names)]
pub fn rsgx_create_rsa_key_pair(
n_byte_size: i32,
e_byte_size: i32,
n: &mut [u8],
d: &mut [u8],
e: &mut [u8],
p: &mut [u8],
q: &mut [u8],
dmp1: &mut [u8],
dmq1: &mut [u8],
iqmp: &mut [u8],
) -> SgxError {
if (n_byte_size <= 0) || (e_byte_size <= 0) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (n.is_empty()) || (n.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (d.is_empty()) || (d.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (e.is_empty()) || (e.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (p.is_empty()) || (p.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (q.is_empty()) || (q.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (dmp1.is_empty()) || (dmp1.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (dmq1.is_empty()) || (dmq1.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (iqmp.is_empty()) || (iqmp.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
sgx_create_rsa_key_pair(
n_byte_size,
e_byte_size,
n.as_mut_ptr(),
d.as_mut_ptr(),
e.as_mut_ptr(),
p.as_mut_ptr(),
q.as_mut_ptr(),
dmp1.as_mut_ptr(),
dmq1.as_mut_ptr(),
iqmp.as_mut_ptr(),
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
fn rsgx_create_rsa_priv2_key(
mod_size: i32,
exp_size: i32,
e: &[u8],
p: &[u8],
q: &[u8],
dmp1: &[u8],
dmq1: &[u8],
iqmp: &[u8],
new_pri_key: &mut sgx_rsa_key_t,
) -> sgx_status_t {
if (mod_size <= 0) || (exp_size <= 0) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (e.is_empty()) || (e.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (p.is_empty()) || (p.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (q.is_empty()) || (q.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (dmp1.is_empty()) || (dmp1.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (dmq1.is_empty()) || (dmq1.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (iqmp.is_empty()) || (iqmp.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_create_rsa_priv2_key(
mod_size,
exp_size,
e.as_ptr(),
p.as_ptr(),
q.as_ptr(),
dmp1.as_ptr(),
dmq1.as_ptr(),
iqmp.as_ptr(),
new_pri_key as *mut sgx_rsa_key_t,
)
}
}
fn rsgx_create_rsa_priv1_key(
n_size: i32,
e_size: i32,
d_size: i32,
n: &[u8],
e: &[u8],
d: &[u8],
new_pri_key: &mut sgx_rsa_key_t,
) -> sgx_status_t {
if (n_size <= 0) || (e_size <= 0) || (d_size <= 0) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (n.is_empty()) || (n.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (e.is_empty()) || (e.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (d.is_empty()) || (d.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_create_rsa_priv1_key(
n_size,
e_size,
d_size,
n.as_ptr(),
e.as_ptr(),
d.as_ptr(),
new_pri_key as *mut sgx_rsa_key_t,
)
}
}
fn rsgx_create_rsa_pub1_key(
mod_size: i32,
exp_size: i32,
n: &[u8],
e: &[u8],
new_pub_key: &mut sgx_rsa_key_t,
) -> sgx_status_t {
if (mod_size <= 0) || (exp_size <= 0) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (n.is_empty()) || (n.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if (e.is_empty()) || (e.len() > i32::MAX as usize) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_create_rsa_pub1_key(
mod_size,
exp_size,
n.as_ptr(),
e.as_ptr(),
new_pub_key as *mut sgx_rsa_key_t,
)
}
}
fn rsgx_free_rsa_key(
rsa_key: sgx_rsa_key_t,
key_type: sgx_rsa_key_type_t,
mod_size: i32,
exp_size: i32,
) -> sgx_status_t {
if (mod_size <= 0) || (exp_size <= 0) {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe { sgx_free_rsa_key(rsa_key, key_type, mod_size, exp_size) }
}
fn rsgx_rsa_priv_decrypt_sha256(
rsa_key: sgx_rsa_key_t,
out_data: &mut [u8],
out_len: &mut usize,
in_data: &[u8],
) -> sgx_status_t {
if in_data.is_empty() {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if *out_len != 0 && out_data.len() != *out_len {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
let p_out_data: *mut u8 = if *out_len != 0 {
out_data.as_mut_ptr()
} else {
ptr::null_mut()
};
sgx_rsa_priv_decrypt_sha256(
rsa_key,
p_out_data,
out_len as *mut usize,
in_data.as_ptr(),
in_data.len(),
)
}
}
fn rsgx_rsa_pub_encrypt_sha256(
rsa_key: sgx_rsa_key_t,
out_data: &mut [u8],
out_len: &mut usize,
in_data: &[u8],
) -> sgx_status_t {
if in_data.is_empty() {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if *out_len != 0 && out_data.len() != *out_len {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
let p_out_data: *mut u8 = if *out_len != 0 {
out_data.as_mut_ptr()
} else {
ptr::null_mut()
};
sgx_rsa_pub_encrypt_sha256(
rsa_key,
p_out_data,
out_len as *mut usize,
in_data.as_ptr(),
in_data.len(),
)
}
}
pub struct SgxRsaPrivKey {
key: RefCell<sgx_rsa_key_t>,
mod_size: Cell<i32>,
exp_size: Cell<i32>,
createflag: Cell<bool>,
}
impl SgxRsaPrivKey {
pub fn new() -> SgxRsaPrivKey {
SgxRsaPrivKey {
key: RefCell::new(ptr::null_mut() as sgx_rsa_key_t),
mod_size: Cell::new(0),
exp_size: Cell::new(0),
createflag: Cell::new(false),
}
}
#[inline]
pub fn create(
&self,
mod_size: i32,
exp_size: i32,
e: &[u8],
p: &[u8],
q: &[u8],
dmp1: &[u8],
dmq1: &[u8],
iqmp: &[u8],
) -> SgxError {
self.create2(mod_size, exp_size, e, p, q, dmp1, dmq1, iqmp)
}
pub fn create2(
&self,
mod_size: i32,
exp_size: i32,
e: &[u8],
p: &[u8],
q: &[u8],
dmp1: &[u8],
dmq1: &[u8],
iqmp: &[u8],
) -> SgxError {
if self.createflag.get() {
return Ok(());
}
let ret = rsgx_create_rsa_priv2_key(
mod_size,
exp_size,
e,
p,
q,
dmp1,
dmq1,
iqmp,
self.key.borrow_mut().deref_mut(),
);
match ret {
sgx_status_t::SGX_SUCCESS => {
self.mod_size.set(mod_size);
self.exp_size.set(exp_size);
self.createflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
pub fn create1(
&self,
mod_size: i32,
exp_size: i32,
priv_exp_size: i32,
n: &[u8],
e: &[u8],
d: &[u8],
) -> SgxError {
if self.createflag.get() {
return Ok(());
}
let ret = rsgx_create_rsa_priv1_key(
mod_size,
exp_size,
priv_exp_size,
n,
e,
d,
self.key.borrow_mut().deref_mut(),
);
match ret {
sgx_status_t::SGX_SUCCESS => {
self.mod_size.set(mod_size);
self.exp_size.set(exp_size);
self.createflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
pub fn decrypt_sha256(
&self,
out_data: &mut [u8],
out_len: &mut usize,
in_data: &[u8],
) -> SgxError {
if !self.createflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_rsa_priv_decrypt_sha256(*self.key.borrow(), out_data, out_len, in_data);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn free(&self) -> SgxError {
if !self.createflag.get() {
return Ok(());
}
let ret = {
let key = *self.key.borrow();
if key.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_free_rsa_key(
key,
sgx_rsa_key_type_t::SGX_RSA_PRIVATE_KEY,
self.mod_size.get(),
self.exp_size.get(),
)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.createflag.set(false);
*self.key.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxRsaPrivKey {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxRsaPrivKey {
fn drop(&mut self) {
let _ = self.free();
}
}
pub struct SgxRsaPubKey {
key: RefCell<sgx_rsa_key_t>,
mod_size: Cell<i32>,
exp_size: Cell<i32>,
createflag: Cell<bool>,
}
impl SgxRsaPubKey {
pub fn new() -> SgxRsaPubKey {
SgxRsaPubKey {
key: RefCell::new(ptr::null_mut() as sgx_rsa_key_t),
mod_size: Cell::new(0),
exp_size: Cell::new(0),
createflag: Cell::new(false),
}
}
pub fn create(&self, mod_size: i32, exp_size: i32, n: &[u8], e: &[u8]) -> SgxError {
if self.createflag.get() {
return Ok(());
}
let ret =
rsgx_create_rsa_pub1_key(mod_size, exp_size, n, e, self.key.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => {
self.mod_size.set(mod_size);
self.exp_size.set(exp_size);
self.createflag.set(true);
Ok(())
}
_ => Err(ret),
}
}
pub fn encrypt_sha256(
&self,
out_data: &mut [u8],
out_len: &mut usize,
in_data: &[u8],
) -> SgxError {
if !self.createflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_rsa_pub_encrypt_sha256(*self.key.borrow(), out_data, out_len, in_data);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn free(&self) -> SgxError {
if !self.createflag.get() {
return Ok(());
}
let ret = {
let key = *self.key.borrow();
if key.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_free_rsa_key(
key,
sgx_rsa_key_type_t::SGX_RSA_PUBLIC_KEY,
self.mod_size.get(),
self.exp_size.get(),
)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.createflag.set(false);
*self.key.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxRsaPubKey {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxRsaPubKey {
fn drop(&mut self) {
let _ = self.free();
}
}
///
/// rsgx_calculate_ecdsa_priv_key generates an ECDSA private key based on an input random seed.
///
/// # Description
///
/// This function generates an ECDSA private key based on an input random seed.
///
/// # Parameters
///
/// **hash_drg**
///
/// Pointer to the input random seed.
///
/// **sgx_nistp256_r_m1**
///
/// Pointer to the buffer for n-1 where n is order of the ECC group used.
///
/// **out_key**
///
/// Pointer to the generated ECDSA private key.
///
/// # Requirements
///
/// Library: libsgx_tcrypto.a
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Some of the pointers are NULL, or the input size is 0.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Unexpected error occurred during the ECDSA private key generation.
///
pub fn rsgx_calculate_ecdsa_priv_key(
hash_drg: &[u8],
sgx_nistp256_r_m1: &[u8],
out_key: &mut [u8],
) -> SgxError {
if (hash_drg.is_empty()) || (hash_drg.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (sgx_nistp256_r_m1.is_empty()) || (sgx_nistp256_r_m1.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (out_key.is_empty()) || (out_key.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let ret = unsafe {
sgx_calculate_ecdsa_priv_key(
hash_drg.as_ptr(),
hash_drg.len() as i32,
sgx_nistp256_r_m1.as_ptr(),
sgx_nistp256_r_m1.len() as i32,
out_key.as_mut_ptr(),
out_key.len() as i32,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn rsgx_ecc256_calculate_pub_from_priv(
priv_key: &sgx_ec256_private_t,
pub_key: &mut sgx_ec256_public_t,
) -> SgxError {
let ret = unsafe {
sgx_ecc256_calculate_pub_from_priv(
priv_key as *const sgx_ec256_private_t,
pub_key as *mut sgx_ec256_public_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn rsgx_ecc256_priv_key(
hash_drg: &[u8],
sgx_nistp256_r_m1: &[u8],
) -> SgxResult<sgx_ec256_private_t> {
if (hash_drg.is_empty()) || (hash_drg.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if (sgx_nistp256_r_m1.is_empty()) || (sgx_nistp256_r_m1.len() > i32::MAX as usize) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let mut priv_key = sgx_ec256_private_t::default();
let ret = unsafe {
sgx_calculate_ecdsa_priv_key(
hash_drg.as_ptr(),
hash_drg.len() as i32,
sgx_nistp256_r_m1.as_ptr(),
sgx_nistp256_r_m1.len() as i32,
&mut priv_key as *mut sgx_ec256_private_t as *mut u8,
mem::size_of::<sgx_ec256_private_t>() as i32,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(priv_key),
_ => Err(ret),
}
}
pub fn rsgx_ecc256_pub_from_priv(priv_key: &sgx_ec256_private_t) -> SgxResult<sgx_ec256_public_t> {
let mut pub_key = sgx_ec256_public_t::default();
let ret = unsafe {
sgx_ecc256_calculate_pub_from_priv(
priv_key as *const sgx_ec256_private_t,
&mut pub_key as *mut sgx_ec256_public_t,
)
};
match ret {
sgx_status_t::SGX_SUCCESS => Ok(pub_key),
_ => Err(ret),
}
}
fn rsgx_aes_gcm128_enc_init(
key: &sgx_aes_gcm_128bit_key_t,
iv: &[u8],
aad: &[u8],
aes_gcm_state: &mut sgx_aes_state_handle_t,
) -> sgx_status_t {
let iv_len = iv.len();
if iv_len != SGX_AESGCM_IV_SIZE {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
let aad_len = aad.len();
if aad_len > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
let p_aad = if !aad.is_empty() {
aad.as_ptr()
} else {
ptr::null()
};
sgx_aes_gcm128_enc_init(
key as *const sgx_aes_gcm_128bit_key_t as *const u8,
iv.as_ptr(),
iv_len as u32,
p_aad,
aad_len as u32,
aes_gcm_state as *mut sgx_aes_state_handle_t,
)
}
}
fn rsgx_aes_gcm128_enc_update(
src: &[u8],
dst: &mut [u8],
aes_gcm_state: sgx_aes_state_handle_t,
) -> sgx_status_t {
let src_len = src.len();
if src_len > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if src_len == 0 {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
let dst_len = dst.len();
if dst_len > u32::MAX as usize {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
if dst_len == 0 || dst_len < src_len {
return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
}
unsafe {
sgx_aes_gcm128_enc_update(
src.as_ptr(),
src_len as u32,
dst.as_mut_ptr(),
aes_gcm_state,
)
}
}
fn rsgx_aes_gcm128_enc_get_mac(
mac: &mut sgx_aes_gcm_128bit_tag_t,
aes_gcm_state: sgx_aes_state_handle_t,
) -> sgx_status_t {
unsafe {
sgx_aes_gcm128_enc_get_mac(
mac as *mut sgx_aes_gcm_128bit_tag_t as *mut u8,
aes_gcm_state,
)
}
}
fn rsgx_aes_gcm_close(aes_gcm_state: sgx_aes_state_handle_t) -> sgx_status_t {
unsafe { sgx_aes_gcm_close(aes_gcm_state) }
}
pub struct SgxAesHandle {
handle: RefCell<sgx_aes_state_handle_t>,
initflag: Cell<bool>,
}
impl SgxAesHandle {
pub fn new() -> SgxAesHandle {
SgxAesHandle {
handle: RefCell::new(ptr::null_mut() as sgx_aes_state_handle_t),
initflag: Cell::new(false),
}
}
pub fn init(&self, key: &sgx_aes_gcm_128bit_key_t, iv: &[u8], aad: &[u8]) -> SgxError {
if self.initflag.get() {
return Ok(());
}
let ret = rsgx_aes_gcm128_enc_init(key, iv, aad, self.handle.borrow_mut().deref_mut());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn update(&self, src: &[u8], dst: &mut [u8]) -> SgxError {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ret = rsgx_aes_gcm128_enc_update(src, dst, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
pub fn get_mac(&self) -> SgxResult<sgx_aes_gcm_128bit_tag_t> {
if !self.initflag.get() {
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let mut mac = sgx_aes_gcm_128bit_tag_t::default();
let ret = rsgx_aes_gcm128_enc_get_mac(&mut mac, *self.handle.borrow());
match ret {
sgx_status_t::SGX_SUCCESS => Ok(mac),
_ => Err(ret),
}
}
pub fn close(&self) -> SgxError {
if !self.initflag.get() {
return Ok(());
}
let ret = {
let handle = *self.handle.borrow();
if handle.is_null() {
sgx_status_t::SGX_SUCCESS
} else {
rsgx_aes_gcm_close(handle)
}
};
match ret {
sgx_status_t::SGX_SUCCESS => {
self.initflag.set(false);
*self.handle.borrow_mut() = ptr::null_mut();
Ok(())
}
_ => Err(ret),
}
}
}
impl Default for SgxAesHandle {
fn default() -> Self {
Self::new()
}
}
impl Drop for SgxAesHandle {
fn drop(&mut self) {
let _ = self.close();
}
}