| use crate::{Attribute, Error, ObjHandle, Result, TransientObject}; |
| use optee_utee_sys as raw; |
| use std::{mem, ptr}; |
| |
| /// Specify one of the available cryptographic operations. |
| #[repr(u32)] |
| pub enum OperationMode { |
| /// Encryption mode |
| Encrypt = 0, |
| /// Decryption mode |
| Decrypt = 1, |
| /// Signature generation mode |
| Sign = 2, |
| /// Signature verfication mode |
| Verify = 3, |
| /// MAC mode |
| Mac = 4, |
| /// Digest mode |
| Digest = 5, |
| /// Key derivation mode |
| Derive = 6, |
| /// Reserve for testing and validation |
| IllegalValue = 0x7fffffff, |
| } |
| |
| /// Represent the information about a crypto information. |
| pub struct OperationInfo { |
| raw: raw::TEE_OperationInfo, |
| } |
| |
| impl OperationInfo { |
| /// Return the `OperationInfo` struct based on the raw struct `TEE_OperationInfo`. |
| /// |
| /// The raw structure contains following fields: |
| /// |
| /// 1) `algorithm`: One of the algorithm of [AlgorithmId](AlgorithmId). |
| /// 2) `mode`: One of the mode of [OperationMode](OperationMode). |
| /// 3) `maxKeySize`: The maximum key sizes of different algorithms as defined in |
| /// [TransientObjectType](../object/enum.TransientObjectType.html). |
| /// 4) `operationClass`: One of the constants from [OperationConstant](OperationConstant). |
| /// 5) `keySize`: |
| /// 5.1) For an operation that makes no use of keys, 0. |
| /// 5.2) For an operation that uses a single key, the actual size of this key. |
| /// 5.3) For an operation that uses multiple keys, 0. (The actual value of `keySize` can be obtained from |
| /// [OperationInfoMultiple](OperationInfoMultiple)). |
| /// 6) `requiredKeyUsage`: |
| /// 6.1) For an operation that makes no use of keys, 0. |
| /// 6.2) For an operation that uses a single key, a bit vector that describes the necessary bits in the object |
| /// usage for `set_key` functions to succeed without panicking. |
| /// 6.3) For an operation that uses multiple keys, 0. (The actual value of `requiredKeyUsage` can be obtained from |
| /// [OperationInfoMultiple](OperationInfoMultiple). |
| /// 7) `digestLength`: For a [Mac](Mac), [AE](AE), or [Digest](Digest), describes the number of bytes in the digest or tag. |
| /// 8) `handleState`: A bit vector describing the current state of the operation. Contains one or more of the |
| /// [HandleFlag](../object/struct.HandleFlag.html). |
| pub fn from_raw(raw: raw::TEE_OperationInfo) -> Self { |
| Self { raw } |
| } |
| |
| /// Return the `keySize` field of the raw structure `TEE_OperationInfo`. |
| pub fn key_size(&self) -> u32 { |
| self.raw.keySize |
| } |
| |
| /// Return the `maxDataSize` field of the raw structure `TEE_OperationInfo`. |
| pub fn max_key_size(&self) -> u32 { |
| self.raw.maxKeySize |
| } |
| } |
| |
| /// Every operation of [AE](AE), [Asymmetric](Asymmetric), [Cipher](Cipher), |
| /// [DeriveKey](DeriveKey), [Digest](Digest), [Mac](Mac) can be either one of the two states. |
| #[repr(u32)] |
| pub enum OperationStates { |
| /// Nothing is going on. |
| Initial = 0x00000000, |
| /// An operation is in progress. |
| Active = 0x00000001, |
| } |
| |
| /// Define the supported crypto operation. |
| pub enum OperationConstant { |
| /// [Cipher](Cipher) |
| Cipher = 1, |
| /// [Mac](Mac) |
| Mac = 3, |
| /// [AE](AE) |
| Ae = 4, |
| /// [Digest](Digest) |
| Digest = 5, |
| /// [Asymmetric](Asymmetric) |
| AsymmetricCipher = 6, |
| /// [Asymmetric](Asymmetric) |
| AsymmetricSignature = 7, |
| /// [DeriveKey](DeriveKey) |
| KeyDerivation = 8, |
| } |
| |
| /// Represent the information about a crypto information which uses multiple keys. |
| pub struct OperationInfoMultiple { |
| raw: *mut raw::TEE_OperationInfoMultiple, |
| size: usize, |
| } |
| |
| impl OperationInfoMultiple { |
| /// Return the `OperationInfoMultiple` struct based on the raw struct `TEE_OperationInfo`. |
| /// |
| /// The raw structure contains following fields: |
| /// |
| /// 1) `algorithm`: One of the algorithm of [AlgorithmId](AlgorithmId). |
| /// 2) `mode`: One of the mode of [OperationMode](OperationMode). |
| /// 3) `maxKeySize`: The maximum key sizes of different algorithms as defined in |
| /// [TransientObjectType](../object/enum.TransientObjectType.html). |
| /// 4) `operationClass`: One of the constants from [OperationConstant](OperationConstant). |
| /// 5) `digestLength`: For a [Mac](Mac), [AE](AE), or [Digest](Digest), describes the number of bytes in the digest or tag. |
| /// 6) `handleState`: A bit vector describing the current state of the operation. Contains one or more of the [HandleFlag](../object/struct.HandleFlag.html). |
| /// 7) `operationState`: Every operation has two states which are defined as |
| /// [OperationStates](OperationStates). |
| /// 8) `numberOfKeys`: This is set to the number of keys required by this operation. May be 0 for an operation which requires no keys. |
| /// 9) `keyInformation`: This array contains numberOfKeys entries, each of which defines the details for one key used by the operation, |
| /// in the order they are defined. |
| /// If the buffer is larger than required to support `numberOfKeys` entries, the additional space is not initialized or modified. |
| /// For each element: |
| /// 9.1) `keySize`: If a key is programmed in the operation, the actual size of this key, otherwise 0. |
| /// 9.2) `requiredKeyUsage`: A bit vector that describes the necessary bits in the object usage for `set_key` or `set_key_2` to succeed without panicking. |
| pub fn from_raw(raw: *mut raw::TEE_OperationInfoMultiple, size: usize) -> Self { |
| Self { raw, size } |
| } |
| |
| /// Return the raw struct `TEE_OperationInfoMultiple`. |
| pub fn raw(&self) -> *mut raw::TEE_OperationInfoMultiple { |
| self.raw |
| } |
| |
| /// Return the `size` field of the raw structure `TEE_OperationInfoMultiple`. |
| pub fn size(&self) -> usize { |
| self.size |
| } |
| } |
| |
| /// An opaque reference that identifies a particular cryptographic operation. |
| pub struct OperationHandle { |
| raw: *mut raw::TEE_OperationHandle, |
| } |
| |
| impl OperationHandle { |
| fn from_raw(raw: *mut raw::TEE_OperationHandle) -> OperationHandle { |
| Self { raw } |
| } |
| |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| unsafe { *(self.raw) } |
| } |
| |
| fn null() -> Self { |
| OperationHandle::from_raw(ptr::null_mut()) |
| } |
| |
| fn allocate(algo: AlgorithmId, mode: OperationMode, max_key_size: usize) -> Result<Self> { |
| let raw_handle: *mut raw::TEE_OperationHandle = Box::into_raw(Box::new(ptr::null_mut())); |
| match unsafe { |
| raw::TEE_AllocateOperation( |
| raw_handle as *mut _, |
| algo as u32, |
| mode as u32, |
| max_key_size as u32, |
| ) |
| } { |
| raw::TEE_SUCCESS => Ok(Self::from_raw(raw_handle)), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| fn info(&self) -> OperationInfo { |
| let mut raw_info: raw::TEE_OperationInfo = unsafe { mem::zeroed() }; |
| unsafe { raw::TEE_GetOperationInfo(self.handle(), &mut raw_info) }; |
| OperationInfo::from_raw(raw_info) |
| } |
| |
| fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| let mut tmp_size: u32 = 0; |
| match unsafe { |
| raw::TEE_GetOperationInfoMultiple(self.handle(), info_buf.as_ptr() as _, &mut tmp_size) |
| } { |
| raw::TEE_SUCCESS => Ok(OperationInfoMultiple::from_raw( |
| info_buf.as_ptr() as _, |
| tmp_size as usize, |
| )), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| fn reset(&mut self) { |
| unsafe { |
| raw::TEE_ResetOperation(self.handle()); |
| } |
| } |
| |
| fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| match unsafe { raw::TEE_SetOperationKey(self.handle(), object.handle()) } { |
| raw::TEE_SUCCESS => return Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| fn copy<T: OpHandle>(&mut self, src: &T) { |
| unsafe { |
| raw::TEE_CopyOperation(self.handle(), src.handle()); |
| } |
| } |
| } |
| |
| /// determine whether a combination of algId and element is supported |
| pub fn is_algorithm_supported(alg_id: u32, element: u32) -> Result<()> { |
| match unsafe { raw::TEE_IsAlgorithmSupported(alg_id, element) } { |
| raw::TEE_SUCCESS => Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| // free before check it's not null |
| /// Deallocate all resources associated with an operation handle. After this function is called, |
| /// the operation handle is no longer valid. All cryptographic material in the operation is destroyed. |
| impl Drop for OperationHandle { |
| fn drop(&mut self) { |
| unsafe { |
| if self.raw != ptr::null_mut() { |
| raw::TEE_FreeOperation(self.handle()); |
| } |
| Box::from_raw(self.raw); |
| } |
| } |
| } |
| |
| /// A trait for a crypto operation to return its handle. |
| pub trait OpHandle { |
| /// Return the handle of an operation. |
| fn handle(&self) -> raw::TEE_OperationHandle; |
| } |
| |
| /// An operation for digest the message. |
| pub struct Digest(OperationHandle); |
| |
| impl Digest { |
| /// Accumulate message data for hashing. The message does not have to be block aligned. |
| /// Subsequent calls to this function are possible. The operation may be in either |
| /// initial or active state and becomes active. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `chunk`: Chunk of data to be hashed |
| /// |
| /// # Panics |
| /// |
| /// 1) If the operation is not allocated with valid algorithms. |
| /// 2) if input data exceeds maximum length for algorithm. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn update(&self, chunk: &[u8]) { |
| unsafe { |
| raw::TEE_DigestUpdate(self.handle(), chunk.as_ptr() as _, chunk.len() as u32); |
| } |
| } |
| |
| /// Finalize the message digest operation and produces the message hash. Afterwards the |
| /// Message Digest operation is reset to initial state and can be reused. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `chunk`: Last chunk of data to be hashed. |
| /// 2) `hash`: Output buffer filled with the message hash. This buffer should be large enough to |
| /// hold the hash message. The real used size is returned by this function. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let chunk = [0u8;8]; |
| /// let chunk = [1u8;8]; |
| /// let hash = [0u8;32]; |
| /// match Digest::allocate(AlgorithmId::Sha256) { |
| /// Ok(operation) => |
| /// { |
| /// operation.update(&chunk1); |
| /// match operation.do_final(&chunk2, hash) { |
| /// Ok(hash_len) => { |
| /// // ... |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the `hash` is too small. Operation is not finalized for this error. |
| /// |
| /// # Panics |
| /// 1) If the operation is not allocated with valid algorithms. |
| /// 2) if input data exceeds maximum length for algorithm. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| //hash size is dynamic changed so we returned it's updated size |
| pub fn do_final(&self, chunk: &[u8], hash: &mut [u8]) -> Result<usize> { |
| let mut hash_size: u32 = hash.len() as u32; |
| match unsafe { |
| raw::TEE_DigestDoFinal( |
| self.handle(), |
| chunk.as_ptr() as _, |
| chunk.len() as u32, |
| hash.as_mut_ptr() as _, |
| &mut hash_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => return Ok(hash_size as usize), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Create a Digest operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Allocate a new cryptographic operation and sets the mode and algorithm type. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `algo`: One of the algorithms that support Digest as listed in |
| /// [AlgorithmId](AlgorithmId). |
| /// 2) `max_key_size`: The maximum key sizes of different algorithms as defined in |
| /// [TransientObjectType](../object/enum.TransientObjectType.html). |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// match Digest::allocate(AlgorithmId::Sha256) { |
| /// Ok(operation) => |
| /// { |
| /// // ... |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// 1) `OutOfMemory`: If not enough resources are available to allocate the object handle. |
| /// 2) `NotSupported`: If the key size is not supported or the object type is not supported. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the Implementation detects any error associated with this function which is not |
| /// explicitly associated with a defined return code for this function. |
| pub fn allocate(algo: AlgorithmId) -> Result<Self> { |
| match OperationHandle::allocate(algo, OperationMode::Digest, 0) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Return the characteristics of a Digest operation. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// match Digest::allocate(AlgorithmId::Md5, 128) { |
| /// Ok(operation) => |
| /// { |
| /// let info = operation.info(); |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Panics |
| /// 1) If the operation is not a valid opened operation. |
| /// 2) if the Implementation detecs any other error. |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Return the characteristics of a Digest operation with multiple keys. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `info_buf`: The buffer is supposed to save multiple keys, and its size should be large enough before passed in. |
| /// The number of keys about this operation can be calculated as: OperationInfoMultiple::size - |
| /// size_of([OperationInfoMultiple](OperationInfoMultiple)) / size_of ( raw::TEE_OperationInfoKey)+1. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// match Digest::allocate(AlgorithmId::Md5, 128) { |
| /// Ok(operation) => |
| /// { |
| /// let mut buffer = [0u32, 12]; |
| /// match operation.info_multiple(&mut buffer) { |
| /// Ok(info_multiple) => { |
| /// // ... |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors: |
| /// |
| /// 1) `ShortBuffer`: If the `info_buf` is not large enough to hold an |
| /// [OperationInfoMultiple](OperationInfoMultiple) and the corresponding keys. |
| /// |
| /// # Panics: |
| /// |
| /// 1) If operation is not a valid opened object. |
| /// 2) If the Implementation detects any other error. |
| // Here the multiple info total size is not sure |
| // Passed in array is supposed to provide enough size for this struct |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Reset the operation state to the state after initial [allocate](Digest::allocate) with the |
| /// add addition of any keys which were configured subsequent to this so that current operation |
| /// can be reused with the same keys. |
| /// |
| /// # Panics |
| /// |
| /// 1) If operation is not a valid opened object. |
| /// 2) If the key has not been set yet. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn reset(&mut self) { |
| self.0.reset() |
| } |
| |
| /// Copy an operation state to another operation. This also copies the key material associated |
| /// with the source operation. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: the source operation. |
| /// 1.1) If `src` has no key programmed, then the key of this operation is cleared. If there is a key |
| /// programmed in srcOperation, then the maximum key size of current SHALL be greater than or |
| /// equal to the actual key size of src. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// match Digest::allocate(AlgorithmId::Sha256) { |
| /// Ok(operation) => |
| /// { |
| /// match Digest::allocate(AlgorithmId::Sha256) { |
| /// Ok(operation2) => |
| /// { |
| /// // ... |
| /// operation.copy(operation2); |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// 1) If the operation or source operation is not a valid opened operation. |
| /// 2) If the alogirhtm or mode differe in two perations. |
| /// 3) If `src` has akey and its size is greater than the maximum key size of the operation. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for Digest { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for conducting symmetric cipher encryption / decryption. |
| /// This operation defines the way to perform symmetric cipher operations, such as AES. |
| /// They cover both block ciphers and stream ciphers. |
| pub struct Cipher(OperationHandle); |
| |
| impl Cipher { |
| /// Start the symmetric cipher operation. The function should be called after the |
| /// [set_key](Cipher::set_key) or [set_key_2](Cipher::set_key_2). |
| /// |
| /// After called, if the operation is in active state, it is reset and then initialized. |
| /// If the operation is in initial state, it is moved to active state. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `iv`: buffer contains the operation Initialization Vector, which is used for: |
| /// 1.1) [AesCbcNopad](AlgorithmId::AesCbcNopad): IV; |
| /// 1.2) [AesCtr](AlgorithmId::AesCtr): Initial Counter Value; |
| /// 1.3) [AesCts](AlgorithmId::AesCts): IV; |
| /// 1.4) [AesXts](AlgorithmId::AesXts): Tweak Value; |
| /// 1.5) [AesCcm](AlgorithmId::AesCcm): Nonce Value; |
| /// 1.6) [AesGcm](AlgorithmId::AesGcm): Nonce Value; |
| /// 1.7) [AesCbcNopad](AlgorithmId::AesCbcNopad): IV. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Cipher`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) If the IV does not have the length required by the algorithm. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn init(&self, iv: &[u8]) { |
| unsafe { raw::TEE_CipherInit(self.handle(), iv.as_ptr() as _, iv.len() as u32) }; |
| } |
| |
| /// Encrypt or decrypt the source data. |
| /// |
| /// Input data does not have to be a multiple of block size. Subsequent calls to this function are possible. |
| /// Unless one or more calls of this function have supplied sufficient input data, no output is generated. |
| /// The function should be called after the [init](Cipher::init). |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: Input data buffer to be encrypted or decrypted. |
| /// 2) `dest`: Output buffer. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let iv = [0u8, 16]; |
| /// let key = [0u8, 16]; |
| /// let src = [1u8; 4096]; |
| /// let mut dest = [0u8; 4096]; |
| /// match Cipher::allocate(AlgorithmId::AesCtr, 128) { |
| /// Ok(operation) => |
| /// { |
| /// match TransientObject::allocate(TransientObjectType::Aes, 128) { |
| /// Ok(object) => |
| /// { |
| /// let attr = AttributeMemref::from_ref(AttributeId::SecretValue, &key); |
| /// object.populate(&[attr.into()])?; |
| /// operation.set_key(&object)?; |
| /// operation.init(&iv); |
| /// operation.update(&src, &mut dest)?; |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the output buffer is not large enough to contain the output. |
| /// In this case, the input is not fed into the algorithm. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Cipher`. |
| /// 2) If the function is called before [init](Cipher::init) or after |
| /// [do_final](Cipher::do_final). |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn update(&self, src: &[u8], dest: &mut [u8]) -> Result<usize> { |
| let mut dest_size: u32 = dest.len() as u32; |
| match unsafe { |
| raw::TEE_CipherUpdate( |
| self.handle(), |
| src.as_ptr() as _, |
| src.len() as u32, |
| dest.as_mut_ptr() as _, |
| &mut dest_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| return Ok(dest_size as usize); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Finalize the cipher operation, processing data that has not been processed by previous calls |
| /// to [update](Cipher::update) as well as data supplied in `src`. The operation handle can be reused or re-initialized. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: Input data buffer to be encrypted or decrypted. |
| /// 2) `dest`: Output buffer. |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the output buffer is not large enough to contain the output. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Cipher`. |
| /// 2) If the function is called before [init](Cipher::init). |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn do_final(&self, src: &[u8], dest: &mut [u8]) -> Result<usize> { |
| let mut dest_size: u32 = dest.len() as u32; |
| match unsafe { |
| raw::TEE_CipherDoFinal( |
| self.handle(), |
| src.as_ptr() as _, |
| src.len() as u32, |
| dest.as_mut_ptr() as _, |
| &mut dest_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => return Ok(dest_size as usize), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Create a Cipher operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Function usage is similar to [Digest::allocate](Digest::allocate). |
| pub fn allocate(algo: AlgorithmId, mode: OperationMode, max_key_size: usize) -> Result<Self> { |
| match OperationHandle::allocate(algo, mode, max_key_size) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::info](Digest::info). |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Function usage is similar to [Digest::info_multiple](Digest::info_multiple). |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Program the key of Digest operation. That ids, it associates the operation with a key. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `object`: The object can either be a [Transient](../object/struct.TransientObject.html) |
| /// or [Persistent](../object/struct.PersistentObject.html). The key material is copied from |
| /// the key object handle into the operation. After the key has been set, there is no longer |
| /// any link between the operation and the key object. The object handle can be closed or reset |
| /// and this will not affect the operation. This copied material exists until the operation is |
| /// freed or another key is set into the operation. |
| /// |
| /// # Errors |
| /// |
| /// 1) `CorruptObject`: If the object is corrupt. The object handle is closed. |
| /// 2) `StorageNotAvailable`: If the object is stored in a storage area which is |
| /// currently inaccessible. |
| /// |
| /// # Panics |
| /// |
| /// 1) If operation is not a valid opened object. |
| /// 2) If object is not null and is not a valid key object. |
| /// 3) If object is not initialized. |
| /// 4) If the operation expect two keys as [AesXts](AlgorithmId::AesXts). |
| /// 5) If the type, size, or usage of object is not compatible with the algorithm, mode, or size of the operation. |
| /// 6) If operation is not in initial state. |
| /// 7) Hardware or cryptographic algorithm failure. |
| /// 8) If the Implementation detects any other error. |
| pub fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| self.0.set_key(object) |
| } |
| |
| /// Initialize an expisting operation with two keys for [AesXts](AlgorithmId::AesXts). |
| /// |
| /// # Parameters: |
| /// |
| /// object1 and object2 SHALL both be non-NULL or both NULL. object1 and object2 SHALL NOT refer to keys with |
| /// bitwise identical [SecretValue](../object/enum.AttributeId.html#variant.SecretValue) attributes. |
| /// |
| /// # Errors |
| /// |
| /// 1) `CorruptObject`: If the object1 is corrupt. The object handle is closed. |
| /// 2) `CorruptObject2`: If the object2 is corrupt. The object handle is closed. |
| /// 3) `StorageNotAvailable`: If the object1 is stored in a storage area which is |
| /// currently inaccessible. |
| /// 4) `StorageNotAvailable2`: If the object2 is stored in a storage area which is |
| /// currently inaccessible. |
| /// |
| /// # Panics |
| /// |
| /// 1) If operation is not a valid opened object. |
| /// 2) If object1 and object2 are not both null and object1 or object2 or both are not a valid key object. |
| /// 3) If object1 or object2 is not initialized. |
| /// 4) If the operation algorithm is not [AesXts](AlgorithmId::AesXts). |
| /// 5) If the type, size, or usage of any object is not compatible with the algorithm, mode, or size of the operation. |
| /// 6) If operation is not in initial state. |
| /// 7) Hardware or cryptographic algorithm failure. |
| /// 8) If the Implementation detects any other error. |
| pub fn set_key_2<T: ObjHandle, D: ObjHandle>(&self, object1: &T, object2: &D) -> Result<()> { |
| match unsafe { |
| raw::TEE_SetOperationKey2(self.handle(), object1.handle(), object2.handle()) |
| } { |
| raw::TEE_SUCCESS => return Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::copy](Digest::copy). |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for Cipher { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for performing MAC (Message Authentication Code) operations, such as `HMAC` |
| /// or `AES-CMAC` operations. This operation is not used for Authenticated Encryption algorithms, |
| /// which SHALL use the functions defined in [AE](AE). |
| pub struct Mac(OperationHandle); |
| |
| impl Mac { |
| /// Initialize a MAC opeartion. The The function should be called after the |
| /// [set_key](Mac::set_key). |
| /// |
| /// # Parameters |
| /// |
| /// 1) `iv`: Input buffer containing the operation Initialization Vector, if applicable |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Mac`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) If the Initialization Vector does not have the length required by the algorithm. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn init(&self, iv: &[u8]) { |
| unsafe { raw::TEE_MACInit(self.handle(), iv.as_ptr() as _, iv.len() as u32) }; |
| } |
| |
| /// Accumulate data for a MAC calculation. |
| /// |
| /// Input data does not have to be a multiple of block size. Subsequent calls to this function are possible. |
| /// Unless one or more calls of this function have supplied sufficient input data, no output is generated. |
| /// The function should be called after the [init](Mac::init). |
| /// |
| /// # Parameters |
| /// |
| /// 1) `chunk`: Chunk of the message to be MACed. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Mac`. |
| /// 2) If the function is called before [init](Mac::init) or after |
| /// [compute_final](Mac::compute_final) or after [compare_final](Mac::compare_final). |
| /// 3) If `chunk` excceds maximum length for algorithm. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn update(&self, chunk: &[u8]) { |
| unsafe { raw::TEE_MACUpdate(self.handle(), chunk.as_ptr() as _, chunk.len() as u32) }; |
| } |
| /// Finalize the MAC operation with a last chunk of message, and computes the MAC. |
| /// Afterwards the operation handle can be reused or re-initialized with a new key. |
| /// The operation SHALL be in active state and moves to initial state afterwards. |
| /// |
| /// # Parameters: |
| /// |
| /// `message`: Input buffer containing a last message chunk to MAC |
| /// `mac`: Output buffer filled with the computed MAC, the size should be allocated enough for |
| /// containing the whole computed MAC |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let mut key: [u8; 20] = [ |
| /// 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, |
| /// 0x36, 0x37, 0x38, 0x39, 0x30,]; |
| /// let mut out: [u8; 20] = [0u8; 20]; |
| /// match Mac::allocate(AlgorithmId::HmacSha1, key.len() * 8) { |
| /// Err(e) => return Err(e), |
| /// Ok(mac) => { |
| /// match TransientObject::allocate(TransientObjectType::HmacSha1, key.len() * 8) { |
| /// Err(e) => return Err(e), |
| /// Ok(mut key_object) => { |
| /// let attr = Attribute::from_ref(AttributeId::SecretValue, &key); |
| /// key_object.populate(&[attr.into()])?; |
| /// mac.set_key(&key_object)?; |
| /// } |
| /// } |
| /// mac.init(&[0u8; 0]); |
| /// mac.update(&[0u8; 8]); |
| /// mac.compute_final(&[0u8; 0], &mut out)?; |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the output buffer is not large enough to contain the output. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Mac`. |
| /// 2) If the function is called before before [init](Mac::init) or after |
| /// [compute_final](Mac::compute_final) or after [compare_final](Mac::compare_final). |
| /// 3) If input data exceeds maximum length for algorithm. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn compute_final(&self, message: &[u8], mac: &mut [u8]) -> Result<usize> { |
| let mut mac_size: u32 = mac.len() as u32; |
| match unsafe { |
| raw::TEE_MACComputeFinal( |
| self.handle(), |
| message.as_ptr() as _, |
| message.len() as u32, |
| mac.as_mut_ptr() as _, |
| &mut mac_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => Ok(mac_size as usize), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Finalize the MAC operation and compares the MAC with the buffer passed to the function. |
| /// Afterwards the operation handle can be reused or re-initialized with a new key. |
| /// The operation SHALL be in active state and moves to initial state afterwards. |
| /// |
| /// # Parameters: |
| /// |
| /// `message`: Input buffer containing a last message chunk to MAC |
| /// `mac`: Input buffer containing the MAC to check |
| /// |
| /// # Errors |
| /// |
| /// 1) `MacInvald`: If the computed MAC does not correspond to the value passed in `mac`. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `Mac`. |
| /// 2) If operation is not in active state. |
| /// 3) If input data exceeds maximum length for algorithm. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn compare_final(&self, message: &[u8], mac: &[u8]) -> Result<()> { |
| match unsafe { |
| raw::TEE_MACCompareFinal( |
| self.handle(), |
| message.as_ptr() as _, |
| message.len() as u32, |
| mac.as_ptr() as _, |
| mac.len() as u32, |
| ) |
| } { |
| raw::TEE_SUCCESS => Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Create a Mac operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Function usage is similar to [Digest::allocate](Digest::allocate). |
| pub fn allocate(algo: AlgorithmId, max_key_size: usize) -> Result<Self> { |
| match OperationHandle::allocate(algo, OperationMode::Mac, max_key_size) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::info](Digest::info). |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Function usage is similar to [Digest::info_multiple](Digest::info_multiple). |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Function usage is similar to [Digest::reset](Digest::reset). |
| pub fn reset(&mut self) { |
| self.0.reset() |
| } |
| |
| /// Function usage is similar to [Cipher::set_key](Cipher::set_key). |
| pub fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| self.0.set_key(object) |
| } |
| |
| /// Function usage is similar to [Digest::copy](Digest::copy). |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for Mac { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for conducting authenticated encryption / decryption. |
| pub struct AE(OperationHandle); |
| |
| impl AE { |
| /// Initialize an AE opeartion. |
| /// The operation must be in the initial state and remains in the initial state afterwards. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `nonce`: The peration nonce or IV |
| /// 2) `tag_len`: Size in bits of the tag: |
| /// 2.1) for `AES-GCM`, can be 128, 120, 112, 104, or 96; |
| /// 2.2) for `AES-CCM`, can be 128, 112, 96, 80, 64, 48, or 32. |
| /// 3) `aad_len`: length in bytes of the AAD (Used only for AES-CCM. Ignored for AES-GCM). |
| /// 4) `pay_load_len`: Length in bytes of the payload (Used only for AES-CCM. Ignored for AES-GCM). |
| /// |
| /// # Errors |
| /// |
| /// 1) `NotSupported`: If the `tag_len` is not supported by the algorithm. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `AE`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) If the nonce length is not compatible with the length required by the algorithm. |
| /// 4) If operation is not in initial state. |
| /// 5) Hardware or cryptographic algorithm failure. |
| /// 6) If the Implementation detects any other error. |
| pub fn init( |
| &self, |
| nonce: &[u8], |
| tag_len: usize, |
| aad_len: usize, |
| pay_load_len: usize, |
| ) -> Result<()> { |
| match unsafe { |
| raw::TEE_AEInit( |
| self.handle(), |
| nonce.as_ptr() as _, |
| nonce.len() as u32, |
| tag_len as u32, |
| aad_len as u32, |
| pay_load_len as u32, |
| ) |
| } { |
| raw::TEE_SUCCESS => return Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Feed a new chunk of Additional Authentication Data (AAD) to the AE operation. |
| /// Subsequent calls to this function are possible. |
| /// The operation SHALL be in initial state and remains in initial state afterwards. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `aad_data`: Input buffer containing the chunk of AAD. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `AE`. |
| /// 2) If the function is called before [init](AE::init) or has been finalized. |
| /// 3) For `AES-CCM`, if the `aad_data.len()` exceeds the requirement. |
| /// 4) If operation is not in initial state. |
| /// 5) Hardware or cryptographic algorithm failure. |
| /// 6) If the Implementation detects any other error. |
| pub fn update_aad(&self, aad_data: &[u8]) { |
| unsafe { |
| raw::TEE_AEUpdateAAD(self.handle(), aad_data.as_ptr() as _, aad_data.len() as u32) |
| }; |
| } |
| |
| /// Accumulate data for an Authentication Encryption operation. |
| /// Input data does not have to be a multiple of block size. Subsequent calls to this function are possible. |
| /// Unless one or more calls of this function have supplied sufficient input data, no output is generated. |
| /// The buffers `src` and `dest` SHALL be either completely disjoint or equal in their starting positions. |
| /// The operation may be in either initial or active state and enters active state afterwards if `src.len()` != 0. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: Input data buffer to be encrypted or decrypted. |
| /// 2) `dest`: Output buffer. |
| /// |
| /// # Errors |
| /// |
| /// `ShortBuffer`: If the output buffer is not large enough to contain the output. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `AE`. |
| /// 2) If the function is called before [init](AE::init) or has been finalized. |
| /// 3) For `AES-CCM`, if the AAD length exceeds the requirement. |
| /// 4) For `AES-CCM`, if the payload length is exceeds the requirement. |
| /// 5) Hardware or cryptographic algorithm failure. |
| /// 6) If the Implementation detects any other error. |
| pub fn update(&self, src: &[u8], dest: &mut [u8]) -> Result<usize> { |
| let mut dest_size: u32 = dest.len() as u32; |
| match unsafe { |
| raw::TEE_AEUpdate( |
| self.handle(), |
| src.as_ptr() as _, |
| src.len() as u32, |
| dest.as_mut_ptr() as _, |
| &mut dest_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| return Ok(dest_size as usize); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| /// Process data that has not been processed by previous calls to [update](AE::update) as well as data supplied in `src`. |
| /// It completes the AE operation and computes the tag. |
| /// The buffers `src` and `dest` SHALL be either completely disjoint or equal in their starting positions. |
| /// The operation may be in either initial or active state and enters initial state afterwards. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: Reference to final chunk of input data to be encrypted. |
| /// 2) `dest`: Output buffer. Can be omitted if the output is to be discarded, e.g. because it is known to be empty. |
| /// 3) `tag`: Output buffer filled with the computed tag. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let key = [0xa5u8; 16]; |
| /// let nonce = [0x00u8; 16]; |
| /// let aad = [0xffu8; 16]; |
| /// let clear1 = [0x5au8; 19]; |
| /// let clear2 = [0xa5u8; 13]; |
| /// let mut ciph1 = [0x00u8; 16]; |
| /// let mut ciph2 = [0x00u8; 16]; |
| /// let mut tag = [0x00u8; 16]; |
| /// match AE::allocate(AlgorithmId::AesCcm, OperationMode::Encrypt, 128) { |
| /// Ok(operation) => { |
| /// match TransientObject::allocate(TransientObjectType::Aes, 128) { |
| /// Ok(key_object) => { |
| /// let attr = Attributememref::from_ref(Attributeid::SecretValue, &key); |
| /// key_object.populat(&[attr.into()])?; |
| /// operation.set_key(&key_object)?; |
| /// operation.init(&nonce, 128, 16, 32)?; |
| /// operation.update_aad(&aad); |
| /// operation.update(&clear1, &mut ciph1)?; |
| /// match operation.encrypt_final(&clear2, &mut ciph2) { |
| /// Ok((_ciph_len, _tag_len)) => { |
| /// // ... |
| /// Ok(()), |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// `ShortBuffer`: If the output tag buffer is not large enough to contain the output. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `AE`. |
| /// 2) If the function is called before [init](AE::init) or has been finalized. |
| /// 3) If the required payload length is known but has not been provided. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| // both dest and tag are updated with different size |
| pub fn encrypt_final( |
| &self, |
| src: &[u8], |
| dest: &mut [u8], |
| tag: &mut [u8], |
| ) -> Result<(usize, usize)> { |
| let mut dest_size: u32 = dest.len() as u32; |
| let mut tag_size: u32 = tag.len() as u32; |
| match unsafe { |
| raw::TEE_AEEncryptFinal( |
| self.handle(), |
| src.as_ptr() as _, |
| src.len() as u32, |
| dest.as_mut_ptr() as _, |
| &mut dest_size, |
| tag.as_mut_ptr() as _, |
| &mut tag_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| return Ok((dest_size as usize, tag_size as usize)); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Process data that has not been processed by previous calls to [update](AE::update) as well as data supplied in `src`. |
| /// It completes the AE operation and computes the tag. |
| /// The buffers `src` and `dest` SHALL be either completely disjoint or equal in their starting positions. |
| /// The operation may be in either initial or active state and enters initial state afterwards. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `src`: Reference to final chunk of input data to be decrypted. |
| /// 2) `dest`: Output buffer. Can be omitted if the output is to be discarded, e.g. because it is known to be empty. |
| /// 3) `tag`: Input buffer containing the tag to compare. |
| /// |
| /// # Errors |
| /// |
| /// `ShortBuffer`: If the output buffer is not large enough to contain the output. |
| /// `MacInvalid`: If the computed tag does not match the supplied tag. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `AE`. |
| /// 2) If the function is called before [init](AE::init) or has been finalized. |
| /// 3) If the required payload length is known but has not been provided. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn decrypt_final(&self, src: &[u8], dest: &mut [u8], tag: &[u8]) -> Result<usize> { |
| let mut dest_size: u32 = dest.len() as u32; |
| match unsafe { |
| raw::TEE_AEDecryptFinal( |
| self.handle(), |
| src.as_ptr() as _, |
| src.len() as u32, |
| dest.as_mut_ptr() as _, |
| &mut dest_size, |
| tag.as_ptr() as _, |
| tag.len() as u32, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| return Ok(dest_size as usize); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Create an AE operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Function usage is similar to [Digest::allocate](Digest::allocate). |
| pub fn allocate(algo: AlgorithmId, mode: OperationMode, max_key_size: usize) -> Result<Self> { |
| match OperationHandle::allocate(algo, mode, max_key_size) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::info](Digest::info). |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Function usage is similar to [Digest::info_multiple](Digest::info_multiple). |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Function usage is similar to [Digest::reset](Digest::reset). |
| pub fn reset(&mut self) { |
| self.0.reset() |
| } |
| |
| /// Function usage is similar to [Cipher::set_key](Cipher::set_key). |
| pub fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| self.0.set_key(object) |
| } |
| |
| /// Function usage is similar to [Digest::copy](Digest::copy). |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for AE { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for conducting asymmetric encryption /decryption or asymmetric sign / verify. |
| /// Note that asymmetric encryption is always “single-stage”, |
| /// which differs from [Cipher](Cipher) which are always “multi-stage”. |
| pub struct Asymmetric(OperationHandle); |
| |
| impl Asymmetric { |
| /// Encrypt a message. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `params`: Optional operation parameters. |
| /// 2) `src`: Input plaintext buffer. |
| /// |
| /// # Example |
| /// ```no_run |
| /// let clear = [1u8; 8]; |
| /// match TransientObject::allocate(TransientObjectType::RsaKeypair, 256) { |
| /// Ok(key) => { |
| /// key.generate_key(256, &[])?; |
| /// match Asymmetric::allocate( |
| /// AlgorithmId::RsaesPkcs1V15, |
| /// OperationMode::Encrypt, |
| /// 256) { |
| /// Ok(operation) => { |
| /// operation.set_key(&key)?; |
| /// match operation.encrypt(&[], &clear) { |
| /// Ok(ciph_text) => { |
| /// // Get cipher text as a vector |
| /// // ... |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the output buffer is not large enough to hold the result. |
| /// 2) `BadParameters`: If the length of the input buffer is not consistent with the algorithm or key size. |
| /// 3) `CiphertextInvalid`: If there is an error in the packing used on the ciphertext. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for [Encrypt](OperationMode::Encrypt] of |
| /// `Asymmetric`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| // This function can update output size with short buffer error when buffer is too |
| // short, and example acipher utilizes this feature! |
| // Define this function as unsafe because we need to return Ok for short buffer error. |
| pub fn encrypt(&self, params: &[Attribute], src: &[u8]) -> Result<Vec<u8>> { |
| let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect(); |
| let mut res_size: u32 = self.info().key_size(); |
| let mut res_vec: Vec<u8> = vec![0u8; res_size as usize]; |
| match unsafe { |
| raw::TEE_AsymmetricEncrypt( |
| self.handle(), |
| p.as_ptr() as _, |
| params.len() as u32, |
| src.as_ptr() as _, |
| src.len() as u32, |
| res_vec.as_mut_ptr() as _, |
| &mut res_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| res_vec.truncate(res_size as usize); |
| return Ok(res_vec); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Decrypt a message. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `params`: Optional operation parameters. |
| /// 2) `src`: Input ciphertext buffer. |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If the output buffer is not large enough to hold the result. |
| /// 2) `BadParameters`: If the length of the input buffer is not consistent with the algorithm or key size. |
| /// 3) `CiphertextInvalid`: If there is an error in the packing used on the ciphertext. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for [Decrypt](OperationMode::Decrypt] of |
| /// `Asymmetric`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn decrypt(&self, params: &[Attribute], src: &[u8]) -> Result<Vec<u8>> { |
| let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect(); |
| let mut res_size: u32 = self.info().key_size(); |
| let mut res_vec: Vec<u8> = vec![0u8; res_size as usize]; |
| match unsafe { |
| raw::TEE_AsymmetricDecrypt( |
| self.handle(), |
| p.as_ptr() as _, |
| params.len() as u32, |
| src.as_ptr() as _, |
| src.len() as u32, |
| res_vec.as_mut_ptr() as _, |
| &mut res_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| res_vec.truncate(res_size as usize); |
| return Ok(res_vec); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Sign a message digest. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `params`: Optional operation parameters. |
| /// 2) `digest`: Input buffer containing the input message digest. |
| /// 3) `signature`: Output buffer written with the signature of the digest. |
| /// |
| /// # Errors |
| /// |
| /// 1) `ShortBuffer`: If `signature` is not large enough to hold the result. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for [Sign](OperationMode::Sign] of |
| /// `Asymmetric`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) If the mode is not set as [Sign](OperationMode::Sign]. |
| /// 4) If `digest.len()` is not equal to the hash size of the algorithm. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn sign_digest( |
| &self, |
| params: &[Attribute], |
| digest: &[u8], |
| signature: &mut [u8], |
| ) -> Result<usize> { |
| let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect(); |
| let mut signature_size: u32 = signature.len() as u32; |
| match unsafe { |
| raw::TEE_AsymmetricSignDigest( |
| self.handle(), |
| p.as_ptr() as _, |
| params.len() as u32, |
| digest.as_ptr() as _, |
| digest.len() as u32, |
| signature.as_mut_ptr() as _, |
| &mut signature_size, |
| ) |
| } { |
| raw::TEE_SUCCESS => { |
| return Ok(signature_size as usize); |
| } |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Verify a message digest. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `params`: Optional operation parameters. |
| /// 2) `digest`: Input buffer containing the input message digest. |
| /// 3) `signature`: Input buffer containing the signature to verify. |
| /// |
| /// # Errors |
| /// |
| /// 1) `SignatureInvalid`: If the signature is invalid. |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for [Verify](OperationMode::Verify] of |
| /// `Asymmetric`. |
| /// 2) If no key is programmed in the operation. |
| /// 3) If the mode is not set as [Verify](OperationMode::Verify]. |
| /// 4) If `digest.len()` is not equal to the hash size of the algorithm. |
| /// 3) Hardware or cryptographic algorithm failure. |
| /// 4) If the Implementation detects any other error. |
| pub fn verify_digest( |
| &self, |
| params: &[Attribute], |
| digest: &[u8], |
| signature: &[u8], |
| ) -> Result<()> { |
| let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect(); |
| match unsafe { |
| raw::TEE_AsymmetricVerifyDigest( |
| self.handle(), |
| p.as_ptr() as _, |
| params.len() as u32, |
| digest.as_ptr() as _, |
| digest.len() as u32, |
| signature.as_ptr() as _, |
| signature.len() as u32, |
| ) |
| } { |
| raw::TEE_SUCCESS => Ok(()), |
| code => Err(Error::from_raw_error(code)), |
| } |
| } |
| |
| /// Create an Asymmetric operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Function usage is similar to [Digest::allocate](Digest::allocate). |
| pub fn allocate(algo: AlgorithmId, mode: OperationMode, max_key_size: usize) -> Result<Self> { |
| match OperationHandle::allocate(algo, mode, max_key_size) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::info](Digest::info). |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Function usage is similar to [Digest::info_multiple](Digest::info_multiple). |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Function usage is similar to [Cipher::set_key](Cipher::set_key). |
| pub fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| self.0.set_key(object) |
| } |
| |
| /// Function usage is similar to [Digest::copy](Digest::copy). |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for Asymmetric { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for derive a shared key object. |
| pub struct DeriveKey(OperationHandle); |
| |
| impl DeriveKey { |
| /// Take one of the Asymmetric Derivation Operation Algorithm that supports this operation as |
| /// defined in [AlgorithmId](AlgorithmId), and output a key object. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `params`: For algorithm [DhDeriveSharedSecret][AlgorithmId::DhDeriveSharedSecret], |
| /// [DhPublicValue](../object/enum.AttributeId.html#variant.DhPublicValue) is required as |
| /// the passed in attribute. |
| /// 2) `object`: An uninitialized transient object to be filled with the derived key. |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let attr_prime = AttributeMemref::from_ref(AttributeId::DhPrime, &[23u8]); |
| /// let attr_base = AttributeMemref::from_ref(AttributeId::DhBase, &[5u8]); |
| /// let mut public_1 = [0u8; 32]; |
| /// match TransientObject::allocate(TransientObjectType::DhKeypair, 256) { |
| /// Ok(key_pair_1) => { |
| /// key_pair_1.generate_key(256, &[attr_prime.into(), attr_base.into()])?; |
| /// key_pair_1.ref_attribute(aTTRIBUTEiD::DhPublicValue, &mut public_1)?; |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// |
| /// let attr_prime = AttributeMemref::from_ref(AttributeId::DhPrime, &[23u8]); |
| /// let attr_base = AttributeMemref::from_ref(AttributeId::DhBase, &[5u8]); |
| /// match TransientObject::allocate(TransientObjectType::DhKeypair, 256) { |
| /// Ok(key_pair_2) => { |
| /// key_pair_2.generate_key(256, &[attr_prime.into(), attr_base.into()])?; |
| /// match DeriveKey::allocate(AlgorithmId::DhDeriveSharedSecret, 256) { |
| /// Ok(operation) => { |
| /// operation.set_key(&key_pair_2)?; |
| /// match TransientObject::allocate(TransientObjectType::GenericSecret, |
| /// 256) { |
| /// // Derived key is saved as an transient object |
| /// Ok(derived_key) => { |
| /// let attr_public = AttributeMemref::from_ref(AttributeId::DhPublicValue, &public_1); |
| /// operation.derive(&[attr_public.into()], &mut derived_key); |
| /// // ... |
| /// Ok(()) |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// } |
| /// Err(e) => Err(e), |
| /// } |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// 1) If the algorithm is not a valid algorithm for `DeriveKey`. |
| /// 2) If the `object` is too small for generated value. |
| /// 3) If no key is programmed in the operation. |
| /// 4) Hardware or cryptographic algorithm failure. |
| /// 5) If the Implementation detects any other error. |
| pub fn derive(&self, params: &[Attribute], object: &mut TransientObject) { |
| let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect(); |
| unsafe { |
| raw::TEE_DeriveKey( |
| self.handle(), |
| p.as_ptr() as _, |
| params.len() as u32, |
| object.handle(), |
| ) |
| }; |
| } |
| |
| /// Create a DeriveKey operation without any specific algorithm or other data. |
| pub fn null() -> Self { |
| Self(OperationHandle::null()) |
| } |
| |
| /// Function usage is similar to [Digest::allocate](Digest::allocate). |
| /// Currently only supports [DhDeriveSharedSecret][AlgorithmId::DhDeriveSharedSecret] as |
| /// `algo`. |
| pub fn allocate(algo: AlgorithmId, max_key_size: usize) -> Result<Self> { |
| match OperationHandle::allocate(algo, OperationMode::Derive, max_key_size) { |
| Ok(handle) => Ok(Self(handle)), |
| Err(e) => Err(e), |
| } |
| } |
| |
| /// Function usage is similar to [Digest::info](Digest::info). |
| pub fn info(&self) -> OperationInfo { |
| self.0.info() |
| } |
| |
| /// Function usage is similar to [Digest::info_multiple](Digest::info_multiple). |
| pub fn info_multiple(&self, info_buf: &mut [u8]) -> Result<OperationInfoMultiple> { |
| self.0.info_multiple(info_buf) |
| } |
| |
| /// Function usage is similar to [Cipher::set_key](Cipher::set_key). |
| pub fn set_key<T: ObjHandle>(&self, object: &T) -> Result<()> { |
| self.0.set_key(object) |
| } |
| |
| /// Function usage is similar to [Digest::copy](Digest::copy). |
| pub fn copy<T: OpHandle>(&mut self, src: &T) { |
| self.0.copy(src) |
| } |
| } |
| |
| impl OpHandle for DeriveKey { |
| fn handle(&self) -> raw::TEE_OperationHandle { |
| self.0.handle() |
| } |
| } |
| |
| /// An operation for generating random data. |
| pub struct Random(); |
| |
| impl Random { |
| /// Generate random data. |
| /// |
| /// # Parameters |
| /// |
| /// 1) `res_buffer`: Reference to generated random data |
| /// |
| /// # Example |
| /// |
| /// ```no_run |
| /// let mut res = [0u8;16]; |
| /// Random::generate(&mut res); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// 1) Hardware or cryptographic algorithm failure. |
| /// 2) If the Implementation detects any other error. |
| pub fn generate(res_buffer: &mut [u8]) { |
| unsafe { |
| raw::TEE_GenerateRandom(res_buffer.as_mut_ptr() as _, res_buffer.len() as _); |
| } |
| } |
| } |
| |
| /// Algorithms that can be allocated as an crypto operation. |
| #[repr(u32)] |
| pub enum AlgorithmId { |
| /// [Cipher](Cipher) supported algorithm. |
| AesEcbNopad = 0x10000010, |
| /// [Cipher](Cipher) supported algorithm. |
| AesCbcNopad = 0x10000110, |
| /// [Cipher](Cipher) supported algorithm. |
| AesCtr = 0x10000210, |
| /// [Cipher](Cipher) supported algorithm. |
| AesCts = 0x10000310, |
| /// [Cipher](Cipher) supported algorithm. |
| AesXts = 0x10000410, |
| /// [Mac](Mac) supported algorithm. |
| AesCbcMacNopad = 0x30000110, |
| /// [Mac](Mac) supported algorithm. |
| AesCbcMacPkcs5 = 0x30000510, |
| /// [Mac](Mac) supported algorithm. |
| AesCmac = 0x30000610, |
| /// [AE](AE) supported algorithm. |
| AesCcm = 0x40000710, |
| /// [AE](AE) supported algorithm. |
| AesGcm = 0x40000810, |
| /// [Cipher](Cipher) supported algorithm. |
| DesEcbNopad = 0x10000011, |
| /// [Cipher](Cipher) supported algorithm. |
| DesCbcNopad = 0x10000111, |
| /// [Mac](Mac) supported algorithm. |
| DesCbcMacNopad = 0x30000111, |
| /// [Mac](Mac) supported algorithm. |
| DesCbcMacPkcs5 = 0x30000511, |
| /// [Cipher](Cipher) supported algorithm. |
| Des3EcbNopad = 0x10000013, |
| /// [Cipher](Cipher) supported algorithm. |
| Des3CbcNopad = 0x10000113, |
| /// [Mac](Mac) supported algorithm. |
| Des3CbcMacNopad = 0x30000113, |
| /// [Mac](Mac) supported algorithm. |
| Des3CbcMacPkcs5 = 0x30000513, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15MD5 = 0x70001830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15Sha1 = 0x70002830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15Sha224 = 0x70003830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15Sha256 = 0x70004830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15Sha384 = 0x70005830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15Sha512 = 0x70006830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1V15MD5Sha1 = 0x7000F830, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1PssMgf1Sha1 = 0x70212930, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1PssMgf1Sha224 = 0x70313930, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1PssMgf1Sha256 = 0x70414930, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1PssMgf1Sha384 = 0x70515930, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| RsassaPkcs1PssMgf1Sha512 = 0x70616930, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1V15 = 0x60000130, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1OAepMgf1Sha1 = 0x60210230, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1OAepMgf1Sha224 = 0x60310230, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1OAepMgf1Sha256 = 0x60410230, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1OAepMgf1Sha384 = 0x60510230, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaesPkcs1OAepMgf1Sha512 = 0x60610230, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Encrypt](OperationMode::Encrypt) or [Decrypt](OperationMode::Decrypt) mode. |
| RsaNopad = 0x60000030, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| DSASha1 = 0x70002131, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| DSASha224 = 0x70003131, |
| /// [Asymmetric](Asymmetric) supported algorithm, can be applied with |
| /// [Sign](OperationMode::Sign) or [Verify](OperationMode::Verify) mode. |
| DSASha256 = 0x70004131, |
| /// [DeriveKey](DeriveKey) supported algorithm. |
| DhDeriveSharedSecret = 0x80000032, |
| /// [Digest](Digest) supported algorithm. |
| Md5 = 0x50000001, |
| /// [Digest](Digest) supported algorithm. |
| Sha1 = 0x50000002, |
| /// [Digest](Digest) supported algorithm. |
| Sha224 = 0x50000003, |
| /// [Digest](Digest) supported algorithm. |
| Sha256 = 0x50000004, |
| /// [Digest](Digest) supported algorithm. |
| Sha384 = 0x50000005, |
| /// [Digest](Digest) supported algorithm. |
| Sha512 = 0x50000006, |
| /// [Mac](Mac) supported algorithm. |
| Md5Sha1 = 0x5000000F, |
| /// [Mac](Mac) supported algorithm. |
| HmacMd5 = 0x30000001, |
| /// [Mac](Mac) supported algorithm. |
| HmacSha1 = 0x30000002, |
| /// [Mac](Mac) supported algorithm. |
| HmacSha224 = 0x30000003, |
| /// [Mac](Mac) supported algorithm. |
| HmacSha256 = 0x30000004, |
| /// [Mac](Mac) supported algorithm. |
| HmacSha384 = 0x30000005, |
| /// [Mac](Mac) supported algorithm. |
| HmacSha512 = 0x30000006, |
| /// Reserved for GlobalPlatform compliance test applications. |
| IllegalValue = 0xefffffff, |
| } |
| |
| /// This specification defines support for optional cryptographic elements. |
| #[repr(u32)] |
| pub enum ElementId { |
| /// Where algId fully defines the required support, |
| /// the special value TEE_CRYPTO_ELEMENT_NONE should be used |
| ElementNone = 0x00000000, |
| /// Source: `NIST`, Generic: `Y`, Size: 192 bits |
| EccCurveNistP192 = 0x00000001, |
| /// Source: `NIST`, Generic: `Y`, Size: 224 bits |
| EccCurveNistP224 = 0x00000002, |
| /// Source: `NIST`, Generic: `Y`, Size: 256 bits |
| EccCurveNistP256 = 0x00000003, |
| /// Source: `NIST`, Generic: `Y`, Size: 384 bits |
| EccCurveNistP384 = 0x00000004, |
| /// Source: `NIST`, Generic: `Y`, Size: 521 bits |
| EccCurveNistP521 = 0x00000005, |
| } |