// 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. use crate::{Error, Result}; use bitflags::bitflags; use optee_utee_sys as raw; use std::{marker, mem, ptr}; /// A general attribute (buffer or value) that can be used to populate an object or to specify /// opeation parameters. pub struct Attribute { raw: raw::TEE_Attribute, } impl Attribute { /// Return the raw struct `TEE_Attribute`. pub fn raw(&self) -> raw::TEE_Attribute { self.raw } } /// Convert the buffer attribute [AttributeMemref](AttributeMemref) to the general attribute. impl<'attrref> From> for Attribute { fn from(attr: AttributeMemref) -> Self { Self { raw: attr.raw() } } } /// Convert the value attribute [AttributeValue](AttributeValue) to the general attribute. impl From for Attribute { fn from(attr: AttributeValue) -> Self { Self { raw: attr.raw() } } } /// A buffer attribute. #[derive(Clone, Copy)] pub struct AttributeMemref<'attrref> { raw: raw::TEE_Attribute, _marker: marker::PhantomData<&'attrref mut [u8]>, } impl<'attrref> AttributeMemref<'attrref> { /// Return the raw struct TEE_Attribute. pub fn raw(&self) -> raw::TEE_Attribute { self.raw } fn new_ref() -> Self { let raw = raw::TEE_Attribute { attributeID: 0, content: raw::content { memref: raw::Memref { buffer: 0 as *mut _, size: 0, }, }, }; Self { raw: raw, _marker: marker::PhantomData, } } /// Populate a single attribute with a reference to a buffer. /// /// # Parameters /// /// 1) `id`: The AttributeId[AttributeId] is an identifier of the attribute to populate. /// 2) `buffer`: Input buffer that holds the content of the attribute. /// /// # Example /// /// ```no_run /// let mut attr = AttributeMemref::from_ref(AttributeId::SecretValue, &mut [0u8;1]); /// ``` pub fn from_ref(id: AttributeId, buffer: &'attrref [u8]) -> Self { let mut res = AttributeMemref::new_ref(); unsafe { raw::TEE_InitRefAttribute( &mut res.raw, id as u32, buffer.as_ptr() as *mut _, buffer.len() as u32, ); } res } } /// A value attribute. pub struct AttributeValue { raw: raw::TEE_Attribute, } impl AttributeValue { /// Return the raw struct TEE_Attribute. pub fn raw(&self) -> raw::TEE_Attribute { self.raw } fn new_value() -> Self { let raw = raw::TEE_Attribute { attributeID: 0, content: raw::content { value: raw::Value { a: 0, b: 0 }, }, }; Self { raw } } /// Populate a single attribute with two u32 values. /// /// # Parameters /// /// 1) `id`: The AttributeId[AttributeId] is an identifier of the attribute to populate. /// 2) `a`, `b`: u32 values to assign to the members of the a value attribute. /// /// # Example /// /// ```no_run /// let mut attr = AttributeValue::from_value(AttributeId::SecretValue, 0, 0); /// ``` pub fn from_value(id: AttributeId, a: u32, b: u32) -> Self { let mut res = AttributeValue::new_value(); unsafe { raw::TEE_InitValueAttribute(&mut res.raw, id as u32, a, b); } res } } /// Represent the characteristics of an object. /// This info can be returned by [TransientObject](TransientObject) function /// [info](TransientObject::info) /// or [PersistentObject](PersistentObject) function /// [info](PersistentObject::info). pub struct ObjectInfo { raw: raw::TEE_ObjectInfo, } // Since raw struct is not implemented Copy attribute yet, every item in raw struct needs a function to extract. impl ObjectInfo { /// Return an [ObjectInfo](ObjectInfo) struct based on the raw structrure `TEE_ObjectInfo`. /// The raw structure contains following fields: /// /// 1) `objectType`: The parameter represents one of the /// [TransientObjectType](TransientObjectType). /// 2) `objectSize`: The current size in bits of the object as determined by its attributes. /// This will always be less than or equal to maxObjectSize. Set to 0 for uninitialized and data only objects. /// 3) `maxObjectSize`: The maximum objectSize which this object can represent. /// 3.1) For a [PersistentObject](PersistentObject), set to `objectSize`. /// 3.2) For a [TransientObject](TransientObject), set to the parameter `maxObjectSize` passed to /// [allocate](TransientObject::allocate). /// 4) `objectUsage`: A bit vector of UsageFlag. /// 5) `dataSize`: /// 5.1) For a [PersistentObject](PersistentObject), set to the current size of the data associated with the object. /// 5.2) For a [TransientObject](TransientObject), always set to 0. /// 6) `dataPosition`: /// 6.1) For a [PersistentObject](PersistentObject), set to the current position in the data for this handle. /// Data positions for different handles on the same object may differ. /// 6.2) For a [TransientObject](TransientObject), set to 0. /// 7) `handleFlags`: A bit vector containing one or more [HandleFlag](HandleFlag) or [DataFlag](DataFlag). pub fn from_raw(raw: raw::TEE_ObjectInfo) -> Self { Self { raw } } /// Return the `dataSize` field of the raw structrure `TEE_ObjectInfo`. pub fn data_size(&self) -> usize { self.raw.dataSize as usize } /// Return the `objectSize` field of the raw structrure `TEE_ObjectInfo`. pub fn object_size(&self) -> usize { self.raw.objectSize as usize } } /// Indicate the possible start offset when moving a data position in the data stream associated with a [PersistentObject](PersistentObject). pub enum Whence { /// The data position is set to offset bytes from the beginning of the data stream. DataSeekSet, /// The data position is set to its current position plus offset. DataSeekCur, /// The data position is set to the size of the object data plus offset. DataSeekEnd, } impl Into for Whence { fn into(self) -> raw::TEE_Whence { match self { Whence::DataSeekSet => raw::TEE_Whence::TEE_DATA_SEEK_SET, Whence::DataSeekCur => raw::TEE_Whence::TEE_DATA_SEEK_CUR, Whence::DataSeekEnd => raw::TEE_Whence::TEE_DATA_SEEK_END, } } } /// An opaque handle on an object. pub struct ObjectHandle { raw: *mut raw::TEE_ObjectHandle, } impl ObjectHandle { fn handle(&self) -> raw::TEE_ObjectHandle { unsafe { *(self.raw) } } fn from_raw(raw: *mut raw::TEE_ObjectHandle) -> ObjectHandle { Self { raw } } fn info(&self) -> Result { let mut raw_info: raw::TEE_ObjectInfo = unsafe { mem::zeroed() }; match unsafe { raw::TEE_GetObjectInfo1(self.handle(), &mut raw_info) } { raw::TEE_SUCCESS => Ok(ObjectInfo::from_raw(raw_info)), code => Err(Error::from_raw_error(code)), } } fn restrict_usage(&mut self, obj_usage: UsageFlag) -> Result<()> { match unsafe { raw::TEE_RestrictObjectUsage1(self.handle(), obj_usage.bits()) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } fn ref_attribute(&self, id: AttributeId, buffer: &mut [u8]) -> Result { let mut size = buffer.len() as u32; match unsafe { raw::TEE_GetObjectBufferAttribute( self.handle(), id as u32, buffer as *mut _ as _, &mut size as _, ) } { raw::TEE_SUCCESS => Ok(size as usize), code => Err(Error::from_raw_error(code)), } } fn value_attribute(&self, id: u32) -> Result<(u32, u32)> { let mut value_a: u32 = 0; let mut value_b: u32 = 0; match unsafe { raw::TEE_GetObjectValueAttribute( self.handle(), id, &mut value_a as *mut _, &mut value_b as *mut _, ) } { raw::TEE_SUCCESS => Ok((value_a, value_b)), code => Err(Error::from_raw_error(code)), } } } #[repr(u32)] pub enum ObjectStorageConstants { Private = 0x00000001, IllegalValue = 0x7FFFFFFF, } bitflags! { /// A set of flags that controls the access rights and sharing permissions /// with which the object handle is opened. pub struct DataFlag: u32 { /// The object is opened with the read access right. This allows the /// Trusted Application to call the function `TEE_ReadObjectData`. const ACCESS_READ = 0x00000001; /// The object is opened with the write access right. This allows the /// Trusted Application to call the functions `TEE_WriteObjectData` and /// `TEE_TruncateObjectData`. const ACCESS_WRITE = 0x00000002; /// The object is opened with the write-meta access right. This allows /// the Trusted Application to call the functions /// `TEE_CloseAndDeletePersistentObject1` and `TEE_RenamePersistentObject`. const ACCESS_WRITE_META = 0x00000004; /// The caller allows another handle on the object to be created with /// read access. const SHARE_READ = 0x00000010; /// The caller allows another handle on the object to be created with /// write access. const SHARE_WRITE = 0x00000020; /// * If this flag is present and the object exists, then the object is /// deleted and re-created as an atomic operation: that is, the TA sees /// either the old object or the new one. /// * If the flag is absent and the object exists, then the function /// SHALL return `TEE_ERROR_ACCESS_CONFLICT`. const OVERWRITE = 0x00000400; } } bitflags! { /// A set of flags that defines usages of data in TEE secure storage. pub struct UsageFlag: u32 { /// The object [Attribute](Attribute) can be extracted. const EXTRACTABLE = 0x00000001; /// The object can be used for encrytpion. const ENCRYPT = 0x00000002; /// The object can be used for decrption. const DECRYPT = 0x00000004; /// The object can be used for mac operation. const MAC = 0x00000008; /// The ojbect can be used for signature. const SIGN = 0x00000010; /// The object can be used for verification of a signature. const VERIFY = 0x00000020; /// The object can be used for deriving a key. const DERIVE = 0x00000040; } } /// Miscellaneous constants. #[repr(u32)] pub enum MiscellaneousConstants { /// Maximum offset of a data object. TeeDataMaxPosition = 0xFFFFFFFF, /// Maximum length of an object id. TeeObjectIdMaxLen = 64, } bitflags! { /// A set of flags that defines Handle features. pub struct HandleFlag: u32{ /// Set for a [PersistentObject](PersistentObject). const PERSISTENT = 0x00010000; /// 1) For a [PersistentObject](PersistentObject), always set. /// 2) For a [TransientObject](TransientObject), initially cleared, then set when the object becomes initialized. const INITIALIZED = 0x00020000; /// Following two flags are for crypto operation handles: /// 1) Set if the required operation key has been set. /// 2) Always set for digest operations. const KEY_SET = 0x00040000; /// Set if the algorithm expects two keys to be set, using `TEE_SetOperationKey2`. /// This happens only if algorithm is set to [AesXts](../crypto_op/enum.AlgorithmId.html#variant.AesXts) /// or `TEE_ALG_SM2_KEP`(not supported now). const EXPECT_TWO_KEYS = 0x00080000; } } #[repr(u32)] pub enum AttributeId { /// Used for all secret keys for symmetric ciphers, MACs, and HMACs SecretValue = 0xC0000000, /// RSA modulus: `n` RsaModulus = 0xD0000130, /// RSA public key exponent: `e` RsaPublicExponent = 0xD0000230, /// RSA private key exponent: `d` RsaPrivateExponent = 0xC0000330, /// RSA prime number: `p` RsaPrime1 = 0xC0000430, /// RSA prime number: `q` RsaPrime2 = 0xC0000530, /// RSA exponent: `dp` RsaExponent1 = 0xC0000630, /// RSA exponent: `dq` RsaExponent2 = 0xC0000730, /// RSA coefficient: `iq` RsaCoefficient = 0xC0000830, /// DSA prime number: `p` DsaPrime = 0xD0001031, /// DSA sub prime number: `q` DsaSubprime = 0xD0001131, /// DSA base: `g` DsaBase = 0xD0001231, /// DSA public value: `y` DsaPublicValue = 0xD0000131, /// DSA private value: `x` DsaPrivateValue = 0xC0000231, /// Diffie-Hellman prime number: `p` DhPrime = 0xD0001032, /// Diffie-Hellman sub prime number: `q` DhSubprime = 0xD0001132, /// Diffie-Hellman base: `g` DhBase = 0xD0001232, /// Diffie-Hellman x bits: `l` DhXBits = 0xF0001332, /// Diffie-Hellman public value: `y` DhPublicValue = 0xD0000132, /// Diffie-Hellman public value: `x` DhPrivateValue = 0xC0000232, RsaOaepLabel = 0xD0000930, RsaPssSaltLength = 0xF0000A30, EccPublicValueX = 0xD0000141, EccPublicValueY = 0xD0000241, /// ECC private value: `d` EccPrivateValue = 0xC0000341, /// ECC Curve algorithm EccCurve = 0xF0000441, BitProtected = (1 << 28), BitValue = (1 << 29), } /// Define types of [TransientObject](TransientObject) with predefined maximum sizes. #[repr(u32)] pub enum TransientObjectType { /// 128, 192, or 256 bits Aes = 0xA0000010, /// Always 64 bits including the parity bits. This gives an effective key size of 56 bits Des = 0xA0000011, /// 128 or 192 bits including the parity bits. This gives effective key sizes of 112 or 168 bits Des3 = 0xA0000013, /// Between 64 and 512 bits, multiple of 8 bits HmacMd5 = 0xA0000001, /// Between 80 and 512 bits, multiple of 8 bits HmacSha1 = 0xA0000002, /// Between 112 and 512 bits, multiple of 8 bits HmacSha224 = 0xA0000003, /// Between 192 and 1024 bits, multiple of 8 bits HmacSha256 = 0xA0000004, /// Between 256 and 1024 bits, multiple of 8 bits HmacSha384 = 0xA0000005, /// Between 256 and 1024 bits, multiple of 8 bits HmacSha512 = 0xA0000006, /// The number of bits in the modulus. 256, 512, 768, 1024, 1536 and 2048 bit keys SHALL be supported. /// Support for other key sizes including bigger key sizes is /// implementation-dependent. Minimum key size is 256 bits RsaPublicKey = 0xA0000030, /// Same as [RsaPublicKey](TransientObjectType::RsaPublicKey) key size. RsaKeypair = 0xA1000030, /// Depends on Algorithm: /// 1) [DsaSha1](../crypto_op/enum.AlgorithmId.html#variant.DsaSha1): /// Between 512 and 1024 bits, multiple of 64 bits /// 2) [DsaSha224](../crypto_op/enum.AlgorithmId.html#variant.DsaSha224): 2048 bits /// 3) [DsaSha256](../crypto_op/enum.AlgorithmId.html#variant.DsaSha256): 2048 or 3072 bits DsaPublicKey = 0xA0000031, /// Same as [DsaPublicKey](TransientObjectType::DsaPublicKey) key size. DsaKeypair = 0xA1000031, /// From 256 to 2048 bits, multiple of 8 bits. DhKeypair = 0xA1000032, /// Between 160 and 521 bits. Conditional: Available only if at least /// one of the ECC the curves defined in Table 6-14 with "generic" /// equal to "Y" is supported. EcdsaPublicKey = 0xA0000041, /// Between 160 and 521 bits. Conditional: Available only if at least /// one of the ECC curves defined in Table 6-14 with "generic" equal to /// "Y" is supported. SHALL be same value as for ECDSA public key size. EcdsaKeypair = 0xA1000041, /// Between 160 and 521 bits. Conditional: Available only if at least /// one of the ECC curves defined in Table 6-14 with "generic" equal to /// "Y" is supported. EcdhPublicKey = 0xA0000042, /// Between 160 and 521 bits. Conditional: Available only if at least /// one of the ECC curves defined in Table 6-14 with "generic" equal to /// "Y" is supported. SHALL be same value as for ECDH public key size EcdhKeypair = 0xA1000042, /// Multiple of 8 bits, up to 4096 bits. This type is intended for secret /// data that has been derived from a key derivation scheme. GenericSecret = 0xA0000000, /// Object is corrupted. CorruptedObject = 0xA00000BE, /// 0 – All data is in the associated data stream. Data = 0xA00000BF, } /// A trait for an object (trasient or persistent) to return its handle. pub trait ObjHandle { /// Return the handle of an object. fn handle(&self) -> raw::TEE_ObjectHandle; } /// An object containing attributes but no data stream, which is reclaimed /// when closed or when the TA instance is destroyed. /// Transient objects are used to hold a cryptographic object (key or key-pair). /// /// Contrast [PersistentObject](PersistentObject). pub struct TransientObject(ObjectHandle); impl TransientObject { /// Create a [TransientObject](TransientObject) with a null handle which points to nothing. pub fn null_object() -> Self { Self(ObjectHandle::from_raw(ptr::null_mut())) } /// Allocate an uninitialized [TransientObject](TransientObject), i.e. a container for attributes. /// /// As allocated, the object is uninitialized. /// It can be initialized by subsequently importing the object material, generating an object, /// deriving an object, or loading an object from the Trusted Storage. /// /// # Parameters /// /// 1) `object_type`: Type of uninitialized object container to be created as defined in /// [TransientObjectType](TransientObjectType). /// 2) `max_object_size`: Key Size of the object. Valid values depend on the object type and are /// defined in [TransientObjectType](TransientObjectType). /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => /// { /// // ... /// 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(object_type: TransientObjectType, max_object_size: usize) -> Result { let raw_handle: *mut raw::TEE_ObjectHandle = Box::into_raw(Box::new(ptr::null_mut())); match unsafe { raw::TEE_AllocateTransientObject(object_type as u32, max_object_size as u32, raw_handle) } { raw::TEE_SUCCESS => { let handle = ObjectHandle::from_raw(raw_handle); Ok(Self(handle)) } code => Err(Error::from_raw_error(code)), } } ///Reset a [TransientObject](TransientObject) to its initial state after allocation. ///If the object is currently initialized, the function clears the object of all its material. ///The object is then uninitialized again. pub fn reset(&mut self) { unsafe { raw::TEE_ResetTransientObject(self.handle()); } } /// Populate an uninitialized object container with object attributes passed by the TA in the `attrs` parameter. /// When this function is called, the object SHALL be uninitialized. /// If the object is initialized, the caller SHALL first clear it using the function reset. /// Note that if the object type is a key-pair, then this function sets both the private and public attributes of the keypair. /// /// # Parameters /// /// 1) `attrs`: Array of object attributes. /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => /// { /// let attrs = [AttributeMemref::from_ref(AttributeId::SecretValue, &[0u8;1])]; /// object.populate(&attrs); /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `BadParameters`: If an incorrect or inconsistent attribute value is detected. In this case, /// the content of the object SHALL remain uninitialized. /// /// # Panics /// /// 1) If object is not a valid opened object that is transient and uninitialized. /// 2) If some mandatory attribute is missing. /// 3) If an attribute which is not defined for the object’s type is present in attrs. /// 4) If an attribute value is too big to fit within the maximum object size specified when the object was created. /// 5) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn populate(&mut self, attrs: &[Attribute]) -> Result<()> { let p: Vec = attrs.iter().map(|p| p.raw()).collect(); match unsafe { raw::TEE_PopulateTransientObject(self.0.handle(), p.as_ptr() as _, attrs.len() as u32) } { raw::TEE_SUCCESS => Ok(()), code => return Err(Error::from_raw_error(code)), } } /// Return the characteristics of an object. /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => { /// match object.info() { /// Ok(info) => { /// // ... /// Ok(()) /// } /// Err(e) => Err(e), /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn info(&self) -> Result { self.0.info() } /// Restrict the object usage flags of an object handle to contain at most the flags passed in the obj_usage parameter. /// /// The initial value of the key usage contains all usage flags. /// /// # Parameters /// /// 1) `obj_usage`: New object usage, an OR comination of one or more of the [UsageFlag](UsageFlag). /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => /// { /// object.restrict_usage(UsageFlag::ENCRYPT)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn restrict_usage(&mut self, obj_usage: UsageFlag) -> Result<()> { self.0.restrict_usage(obj_usage) } /// Extract one buffer attribute from an object. The attribute is identified by the argument id. /// /// # Parameters /// /// 1) `id`: Identifier of the attribute to retrieve. /// 2) `ref_attr`: Output buffer to get the content of the attribute. /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => { /// let mut attr = [0u8; 16]; /// match object.ref_attribute(id, &mut attr) { /// Ok(size) => { /// // ... /// Ok(()) /// } /// Err(e) => Err(e), /// } /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `ItemNotFound`: If the attribute is not found on this object. /// 2) `ShortBuffer`: If buffer is NULL or too small to contain the key part. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the object is not initialized. /// 3) If the Attribute is not a buffer attribute. pub fn ref_attribute(&self, id: AttributeId, buffer: &mut [u8]) -> Result { self.0.ref_attribute(id, buffer) } /// Extract one value attribute from an object. The attribute is identified by the argument id. /// /// # Parameters /// /// 1) `id`: Identifier of the attribute to retrieve. /// 2) `value_attr`: Two value placeholders to get the content of the attribute. /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => { /// match object.value_attribute(id) { /// Ok(a,b) => { /// // ... /// Ok(()) /// } /// Err(e) => Err(e), /// } /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `ItemNotFound`: If the attribute is not found on this object. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the object is not initialized. /// 3) If the Attribute is not a value attribute. pub fn value_attribute(&self, id: u32) -> Result<(u32, u32)> { self.0.value_attribute(id) } /// Populates an uninitialized object handle with the attributes of another object handle; /// that is, it populates the attributes of this handle with the attributes of src_handle. /// It is most useful in the following situations: /// 1) To extract the public key attributes from a key-pair object. /// 2) To copy the attributes from a [PersistentObject](PersistentObject) into a [TransientObject](TransientObject). /// /// # Parameters /// /// 1) `src_object`: Can be either a [TransientObject](TransientObject) or [PersistentObject](PersistentObject). /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object1) => /// { /// match TransientObject::allocate(TransientObjectType::Aes, 256) { /// Ok(object2) => { /// object1.copy_attribute_from(object2); /// Ok(()) /// } /// Err(e) => Err(e), /// } /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `CorruptObject`: If the persistentd` object is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If src_object is not initialized. /// 2) If self is initialized. /// 3) If the type and size of src_object and self are not compatible. /// 4) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn copy_attribute_from(&mut self, src_object: &T) -> Result<()> { match unsafe { raw::TEE_CopyObjectAttributes1(self.handle(), src_object.handle()) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } /// Generates a random key or a key-pair and populates a transient key object with the generated key material. /// /// # Parameters /// /// 1) `key_size`: the size of the desired key. It SHALL be less than or equal to /// the maximum key size specified when the [TransientObject](TransientObject) was created. /// /// # Example /// /// ```no_run /// match TransientObject::allocate(TransientObjectType::Aes, 128) { /// Ok(object) => /// { /// object.generate_key(128, &[])?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `BadParameters`: If an incorrect or inconsistent attribute value is detected. In this /// case, the content of the object SHALL remain uninitialized. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If some mandatory attribute is missing. /// 3) If an attribute which is not defined for the object’s type is present in attrs. /// 4) If an attribute value is too big to fit within the maximum object size specified when /// the object was created. /// 5) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn generate_key(&self, key_size: usize, params: &[Attribute]) -> Result<()> { let p: Vec = params.iter().map(|p| p.raw()).collect(); unsafe { match raw::TEE_GenerateKey( self.handle(), key_size as u32, p.as_slice().as_ptr() as _, p.len() as u32, ) { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } } } impl ObjHandle for TransientObject { fn handle(&self) -> raw::TEE_ObjectHandle { self.0.handle() } } impl Drop for TransientObject { /// Deallocates a [TransientObject](TransientObject) previously allocated. /// After this function has been called, the object handle is no longer valid and all resources /// associated with the [TransientObject](TransientObject) SHALL have been reclaimed. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. fn drop(&mut self) { unsafe { if self.0.raw != ptr::null_mut() { raw::TEE_FreeTransientObject(self.0.handle()); } Box::from_raw(self.0.raw); } } } /// An object identified by an Object Identifier and including a Data Stream. /// /// Contrast [TransientObject](TransientObject). pub struct PersistentObject(ObjectHandle); impl PersistentObject { /// Open an existing [PersistentObject](PersistentObject). /// /// # Parameters /// /// 1) `storage_id`: The storaget to use which is defined in /// [ObjectStorageConstants](ObjectStorageConstants). /// 2) `object_id`: The object identifier. Note that this buffer cannot reside in shared memory. /// 3) `flags`: The [DataFlag](DataFlag) which determine the settings under which the object is opened. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_READ) { /// Ok(object) => /// { /// // ... /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `ItemNotFound`: If the storage denoted by storage_id does not exist or if the object /// identifier cannot be found in the storage. /// 2) `Access_Conflict`: If an access right conflict was detected while opening the object. /// 3) `OutOfMemory`: If there is not enough memory to complete the operation. /// 4) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 5) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object_id.len() > /// [MiscellaneousConstants::TeeObjectIdMaxLen](MiscellaneousConstants::TeeObjectIdMaxLen) /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn open( storage_id: ObjectStorageConstants, object_id: &[u8], flags: DataFlag, ) -> Result { let raw_handle: *mut raw::TEE_ObjectHandle = Box::into_raw(Box::new(ptr::null_mut())); match unsafe { raw::TEE_OpenPersistentObject( storage_id as u32, object_id.as_ptr() as _, object_id.len() as u32, flags.bits(), raw_handle as *mut _, ) } { raw::TEE_SUCCESS => { let handle = ObjectHandle::from_raw(raw_handle); Ok(Self(handle)) } code => { unsafe { Box::from_raw(raw_handle); } Err(Error::from_raw_error(code)) } } } /// Create a [PersistentObject](PersistentObject) with initial attributes and an initial data stream content. /// /// # Parameters /// /// 1) `storage_id`: The storaget to use which is defined in /// [ObjectStorageConstants](ObjectStorageConstants). /// 2) `object_id`: The object identifier. Note that this buffer cannot reside in shared memory. /// 3) `flags`: The [DataFlag](DataFlag) which determine the settings under which the object is opened. /// 4) `attributes`: A handle on a [PersistentObject](PersistentObject) or an initialized [TransientObject](TransientObject) /// from which to take the [PersistentObject](PersistentObject) attributes. /// Can be NONE if the [PersistentObject](PersistentObject) contains no attribute. /// For example,if it is a pure data object. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// let mut init_data: [u8; 0] = [0; 0]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_READ | DataFlag::ACCESS_WRITE /// None, /// &mut init_data) { /// Ok(object) => /// { /// // ... /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `ItemNotFound`: If the storage denoted by storage_id does not exist or if the object /// identifier cannot be found in the storage. /// 2) `Access_Conflict`: If an access right conflict was detected while opening the object. /// 3) `OutOfMemory`: If there is not enough memory to complete the operation. /// 4) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 5) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object_id.len() > /// [MiscellaneousConstants::TeeObjectIdMaxLen](MiscellaneousConstants::TeeObjectIdMaxLen). /// 2) If attributes is not NONE and is not a valid handle on an initialized object containing /// the type and attributes of the [PersistentObject](PersistentObject) to create. /// 3) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn create( storage_id: ObjectStorageConstants, object_id: &[u8], flags: DataFlag, attributes: Option, initial_data: &[u8], ) -> Result { let raw_handle: *mut raw::TEE_ObjectHandle = Box::into_raw(Box::new(ptr::null_mut())); let attributes = match attributes { Some(a) => a.handle(), None => ptr::null_mut(), }; match unsafe { raw::TEE_CreatePersistentObject( storage_id as u32, object_id.as_ptr() as _, object_id.len() as u32, flags.bits(), attributes, initial_data.as_ptr() as _, initial_data.len() as u32, raw_handle as *mut _, ) } { raw::TEE_SUCCESS => { let handle = ObjectHandle::from_raw(raw_handle); Ok(Self(handle)) } code => { unsafe { Box::from_raw(raw_handle); } Err(Error::from_raw_error(code)) } } } /// Marks an object for deletion and closes the object. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_READ) { /// Ok(object) => /// { /// object.close_and_delete()?; /// std::mem::forget(object); /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. // this function is conflicted with Drop implementation, when use this one to avoid panic: // Call `mem::forget` for this structure to avoid double drop the object pub fn close_and_delete(&mut self) -> Result<()> { match unsafe { raw::TEE_CloseAndDeletePersistentObject1(self.0.handle()) } { raw::TEE_SUCCESS => { unsafe { Box::from_raw(self.0.raw); } return Ok(()); } code => Err(Error::from_raw_error(code)), } } /// Changes the identifier of an object. /// The object SHALL have been opened with the [DataFlag::ACCESS_WRITE_META](DataFlag::ACCESS_WRITE_META) right, which means access to the object is exclusive. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// let new_obj_id = [2u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_WRITE_META) { /// Ok(object) => /// { /// object.rename(&new_obj_id)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `Access_Conflict`: If an access right conflict was detected while opening the object. /// 2) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 3) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If new_object_id resides in shared memory. /// 3) If new_object_id.len() > /// [MiscellaneousConstants::TeeObjectIdMaxLen](MiscellaneousConstants::TeeObjectIdMaxLen). /// 4) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn rename(&mut self, new_object_id: &[u8]) -> Result<()> { match unsafe { raw::TEE_RenamePersistentObject( self.0.handle(), new_object_id.as_ptr() as _, new_object_id.len() as u32, ) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } /// Return the characteristics of an object. /// Function is similar to [TransientObject::info](TransientObject::info) besides extra errors. /// /// # Errors /// /// 1) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. pub fn info(&self) -> Result { self.0.info() } /// Restrict the object usage flags of an object handle to contain at most the flags passed in the obj_usage parameter. /// Function is similar to [TransientObject::restrict_usage](TransientObject::restrict_usage) besides extra errors. /// /// # Errors /// /// 1) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. pub fn restrict_usage(&mut self, obj_usage: UsageFlag) -> Result<()> { self.0.restrict_usage(obj_usage) } /// Extract one buffer attribute from an object. The attribute is identified by the argument id. /// Function is similar to [TransientObject::ref_attribute](TransientObject::ref_attribute) besides extra errors. /// /// # Errors /// /// 1) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. pub fn ref_attribute(&self, id: AttributeId, buffer: &mut [u8]) -> Result { self.0.ref_attribute(id, buffer) } /// Extract one value attribute from an object. The attribute is identified by the argument id. /// Function is similar to [TransientObject::value_attribute](TransientObject::value_attribute) besides extra errors. /// /// # Errors /// /// 1) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. pub fn value_attribute(&self, id: u32) -> Result<(u32, u32)> { self.0.value_attribute(id) } /// Read requested size from the data stream assoicate with the object into the buffer. /// /// # Parameters /// /// 1) `buffer`: A pre-allocated buffer for saving the object's data stream. /// 2) `count`: The returned value contains the number of bytes read. /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_READ) { /// Ok(object) => /// { /// let read_buf = [0u8;16]; /// object.read(&mut read_buf)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 2) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn read(&self, buf: &mut [u8]) -> Result { let mut count: u32 = 0; match unsafe { raw::TEE_ReadObjectData( self.handle(), buf.as_mut_ptr() as _, buf.len() as u32, &mut count, ) } { raw::TEE_SUCCESS => Ok(count), code => Err(Error::from_raw_error(code)), } } /// Write the passed in buffer data into from the data stream assoicate with the object. /// /// # Parameters /// /// 1) `buffer`: A pre-allocated buffer for saving the object's data stream. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_WRITE) { /// Ok(object) => /// { /// let write_buf = [1u8;16]; /// object.write(& write_buf)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `StorageNoSpace`: If insufficient storage space is available. /// 2) `Overflow`: If the value of the data position indicator resulting from this operation /// would be greater than /// [MiscellaneousConstants::TeeDataMaxPosition](MiscellaneousConstants::TeeDataMaxPosition). /// 3) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 4) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn write(&mut self, buf: &[u8]) -> Result<()> { match unsafe { raw::TEE_WriteObjectData(self.handle(), buf.as_ptr() as _, buf.len() as u32) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } /// Change the size of a data stream associate with the object. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open ( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_WRITE) { /// Ok(object) => /// { /// object.truncate(1u32)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `StorageNoSpace`: If insufficient storage space is available. /// would be greater than /// [MiscellaneousConstants::TeeDataMaxPosition](MiscellaneousConstants::TeeDataMaxPosition). /// 2) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 3) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn truncate(&self, size: u32) -> Result<()> { match unsafe { raw::TEE_TruncateObjectData(self.handle(), size) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } /// Set the data position indicator associate with the object. /// /// # Parameters /// 1) `whence`: Defined in [Whence](Whence). /// 2) `offset`: The bytes shifted based on `whence`. /// /// # Example /// /// ```no_run /// let obj_id = [1u8;1]; /// match PersistentObject::open( /// ObjectStorageConstants::Private, /// &obj_id, /// DataFlag::ACCESS_WRITE) { /// Ok(object) => /// { /// object.seek(0i32, Whence::DataSeekSet)?; /// Ok(()) /// } /// Err(e) => Err(e), /// } /// ``` /// /// # Errors /// /// 1) `Overflow`: If data position indicator is greater than /// [MiscellaneousConstants::TeeDataMaxPosition](MiscellaneousConstants::TeeDataMaxPosition). /// 2) `CorruptObject`: If the [PersistentObject](PersistentObject) is corrupt. The object handle is closed. /// 3) `StorageNotAvailable`: If the [PersistentObject](PersistentObject) is stored in a storage area which is /// currently inaccessible. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. pub fn seek(&self, offset: i32, whence: Whence) -> Result<()> { match unsafe { raw::TEE_SeekObjectData(self.handle(), offset, whence.into()) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } } impl ObjHandle for PersistentObject { fn handle(&self) -> raw::TEE_ObjectHandle { self.0.handle() } } impl Drop for PersistentObject { /// Close an opened [PersistentObject](PersistentObject). /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error associated with this function which is not /// explicitly associated with a defined return code for this function. fn drop(&mut self) { unsafe { if self.0.raw != Box::into_raw(Box::new(ptr::null_mut())) { raw::TEE_CloseObject(self.0.handle()); } Box::from_raw(self.0.raw); } } } // The examples and detailed function explanation will be added after we test this struct and its // functions. /// An enumerator for [PersistentObject](PersistentObject)s. pub struct ObjectEnumHandle { raw: *mut raw::TEE_ObjectEnumHandle, } impl ObjectEnumHandle { /// Allocate an object enumerator. /// Once an object enumerator has been allocated, it can be reused for multiple enumerations. pub fn allocate() -> Result { let raw_handle: *mut raw::TEE_ObjectEnumHandle = Box::into_raw(Box::new(ptr::null_mut())); match unsafe { raw::TEE_AllocatePersistentObjectEnumerator(raw_handle) } { raw::TEE_SUCCESS => Ok(Self { raw: raw_handle }), code => { unsafe { Box::from_raw(raw_handle); } Err(Error::from_raw_error(code)) } } } /// Reset an object enumerator handle to its initial state after allocation. /// If an enumeration has been started, it is stopped. pub fn reset(&mut self) { unsafe { raw::TEE_ResetPersistentObjectEnumerator(*self.raw); } } /// Start the enumeration of all the [PersistentObject](PersistentObject)s in a given Trusted Storage. /// The object information can be retrieved by calling the function /// [ObjectEnumHandle::get_next](ObjectEnumHandle::get_next) repeatedly. pub fn start(&mut self, storage_id: u32) -> Result<()> { match unsafe { raw::TEE_StartPersistentObjectEnumerator(*self.raw, storage_id) } { raw::TEE_SUCCESS => Ok(()), code => Err(Error::from_raw_error(code)), } } /// Get the next object in an enumeration and returns information about the object: type, size, identifier, etc. pub fn get_next( &mut self, object_info: &mut ObjectInfo, object_id: &mut [u8], ) -> Result { let mut object_id_len: u32 = 0; match unsafe { raw::TEE_GetNextPersistentObject( *self.raw, &mut object_info.raw, object_id.as_mut_ptr() as _, &mut object_id_len, ) } { raw::TEE_SUCCESS => Ok(object_id_len), code => Err(Error::from_raw_error(code)), } } } impl Drop for ObjectEnumHandle { /// Deallocates all resources associated with an object enumerator handle. After this function is called, the handle is no longer valid. /// /// # Panics /// /// 1) If object is not a valid opened object. /// 2) If the Implementation detects any other error. fn drop(&mut self) { unsafe { raw::TEE_FreePersistentObjectEnumerator(*self.raw); Box::from_raw(self.raw); } } }