sgx_tseal 1.1.1

Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language.
Documentation
// 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..

//!
//! Intel(R) Software Guard Extensions Sealing and Unsealing Functions
//!
//! # Intel(R) Software Guard Extensions Sealing and Unsealing Functions
//!
//! The API of the model provides the following functions:
//!
//! * Exposes APIs to create sealed data which is both confidentiality andintegrity protected.
//! * Exposes an API to unseal sealed data inside the enclave.
//!
//! The library also provides APIs to help calculate the sealed data size, encrypt text length, and Message Authentication Code (MAC) text length.
//!
use sgx_types::*;
use sgx_types::marker::ContiguousMemory;
use crate::internal::*;
use core::mem;
use core::marker::PhantomData;
use alloc::slice;
use alloc::boxed::Box;

/// The structure about the unsealed data.
pub struct SgxUnsealedData<'a, T: 'a + ?Sized> {
    pub payload_size: u32,
    pub decrypt: Box<T>,
    pub additional: Box<[u8]>,
    marker: PhantomData<&'a T>,
}

impl<'a, T: 'a + ?Sized> SgxUnsealedData<'a, T> {
    ///
    /// Get the payload size of the SgxUnsealedData.
    ///
    pub fn get_payload_size(&self) -> u32 {
        self.payload_size
    }
    ///
    /// Get the pointer of decrypt buffer in SgxUnsealedData.
    ///
    pub fn get_decrypt_txt(&self) -> &T {
        &*self.decrypt
    }
    ///
    /// Get the pointer of additional buffer in SgxUnsealedData.
    ///
    pub fn get_additional_txt(&self) -> &[u8] {
        &*self.additional
    }
}

impl<'a, T: 'a + Default> Default for SgxUnsealedData<'a, T> {
    fn default() -> SgxUnsealedData<'a, T> {
        SgxUnsealedData {
            payload_size: 0_u32,
            decrypt: Box::<T>::default(),
            additional: Box::<[u8]>::default(),
            marker: PhantomData,
        }
    }
}

impl<'a, T: 'a + Default> Default for SgxUnsealedData<'a, [T]> {
    fn default() -> SgxUnsealedData<'a, [T]> {
        SgxUnsealedData {
            payload_size: 0_u32,
            decrypt: Box::<[T]>::default(),
            additional: Box::<[u8]>::default(),
            marker: PhantomData,
        }
    }
}

impl<'a, T: 'a + Clone + ?Sized> Clone for SgxUnsealedData<'a, T> {
    fn clone(&self) -> SgxUnsealedData<'a, T> {
        SgxUnsealedData {
           payload_size: self.payload_size,
           decrypt: self.decrypt.clone(),
           additional: self.additional.clone(),
           marker: PhantomData,
        }
    }
}

/// The structure about the sealed data.
pub struct SgxSealedData<'a, T: 'a + ?Sized> {
    inner: SgxInternalSealedData,
    marker: PhantomData<&'a T>,
}

impl<'a, T: 'a + ?Sized> Default for SgxSealedData<'a, T> {
    fn default() -> SgxSealedData<'a, T> {
        SgxSealedData {
            inner: SgxInternalSealedData::new(),
            marker: PhantomData,
        }
    }
}

impl<'a, T: 'a + Clone + ?Sized> Clone for SgxSealedData<'a, T> {
    fn clone(&self) -> SgxSealedData<'a, T> {
        SgxSealedData {
           inner: self.inner.clone(),
           marker: PhantomData,
        }
    }
}

/// The encrypt_text to seal is T, and T must have Copy and ContiguousMemory trait.
impl<'a, T: 'a + Copy + ContiguousMemory> SgxSealedData<'a, T> {

    ///
    /// This function is used to AES-GCM encrypt the input data. Two input data sets
    /// are provided: one is the data to be encrypted; the second is optional additional data
    /// that will not be encrypted but will be part of the GCM MAC calculation which also covers the data to be encrypted.
    ///
    /// # Description
    ///
    /// The seal_data function retrieves a key unique to the enclave and uses
    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret
    /// data after the enclave is destroyed. The sealed data blob can be
    /// unsealed on future instantiations of the enclave.
    /// The additional data buffer will not be encrypted but will be part of the MAC
    /// calculation that covers the encrypted data as well. This data may include
    /// information about the application, version, data, etc which can be utilized to
    /// identify the sealed data blob since it will remain plain text
    /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
    /// allocate for the `SgxSealedData` structure. The input sealed data buffer and
    /// text2encrypt buffers must be allocated within the enclave.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **additional_text**
    ///
    /// Pointer to the additional Message Authentication Code (MAC) data.
    /// This additional data is optional and no data is necessary.
    ///
    /// **encrypt_text**
    ///
    /// Pointer to the data stream to be encrypted, which is &T. Must be within the enclave.
    ///
    /// # Return value
    ///
    /// The sealed data in SgxSealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// Indicates an error if the parameters do not meet any of the following conditions:
    ///
    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
    /// * encrypt_text must be non-zero.
    /// * encrypt_text buffer must be within the enclave.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn seal_data(additional_text: &[u8], encrypt_text: &'a T) -> SgxResult<Self> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_slice: &[u8] = unsafe {
            slice::from_raw_parts(encrypt_text as *const _ as *const u8, mem::size_of_val(encrypt_text))
        };
        let result = SgxInternalSealedData::seal_data(additional_text, encrypt_slice);
        result.map(|x| {
            SgxSealedData {
                inner: x,
                marker: PhantomData,
            }
        })
    }

    ///
    /// This function is used to AES-GCM encrypt the input data. Two input data sets
    /// are provided: one is the data to be encrypted; the second is optional additional
    /// data that will not be encrypted but will be part of the GCM MAC calculation
    /// which also covers the data to be encrypted. This is the expert mode
    /// version of function `seal_data`.
    ///
    /// # Descryption
    ///
    /// The `seal_data_ex` is an extended version of `seal_data`. It
    /// provides parameters for you to identify how to derive the sealing key (key
    /// policy and attributes_mask). Typical callers of the seal library should be
    /// able to use `seal_data` and the default values provided for key_
    /// policy (MR_SIGNER) and an attribute mask which includes the RESERVED,
    /// INITED and DEBUG bits. Users of this function should have a clear understanding
    /// of the impact on using a policy and/or attribute_mask that is different from that in seal_data.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **key_policy**
    ///
    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy.
    ///
    /// Key policy name | Value | Description
    /// ---|---|---
    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register
    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register
    ///
    /// **attribute_mask**
    ///
    /// Identifies which platform/enclave attributes to use in the key derivation. See
    /// the definition of sgx_attributes_t to determine which attributes will be
    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0.
    ///
    /// **misc_mask**
    ///
    /// The misc mask bits for the enclave. Reserved for future function extension.
    ///
    /// **additional_text**
    ///
    /// Pointer to the additional Message Authentication Code (MAC) data.
    /// This additional data is optional and no data is necessary.
    ///
    /// **encrypt_text**
    ///
    /// Pointer to the data stream to be encrypted, which is &T. Must not be NULL. Must be within the enclave.
    ///
    /// # Return value
    ///
    /// The sealed data in SgxSealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// Indicates an error if the parameters do not meet any of the following conditions:
    ///
    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
    /// * encrypt_text must be non-zero.
    /// * encrypt_text buffer must be within the enclave.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn seal_data_ex(key_policy: u16,
                        attribute_mask: sgx_attributes_t,
                        misc_mask: sgx_misc_select_t,
                        additional_text: &[u8],
                        encrypt_text: &'a T) -> SgxResult<Self> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_slice: &[u8] = unsafe {
            slice::from_raw_parts(encrypt_text as *const _ as *const u8, mem::size_of_val(encrypt_text))
        };
        let result = SgxInternalSealedData::seal_data_ex(key_policy,
                                                         attribute_mask,
                                                         misc_mask,
                                                         additional_text,
                                                         encrypt_slice);
        result.map(|x| {
            SgxSealedData {
                inner: x,
                marker: PhantomData,
            }
        })
    }

    ///
    /// This function is used to AES-GCM decrypt the input sealed data structure.
    /// Two output data sets result: one is the decrypted data; the second is the
    /// optional additional data that was part of the GCM MAC calculation but was not
    /// encrypted. This function provides the converse of seal_data and
    /// seal_data_ex.
    ///
    /// # Descryption
    ///
    /// The unseal_data function AES-GCM decrypts the sealed data so that
    /// the enclave data can be restored. This function can be utilized to restore
    /// secret data that was preserved after an earlier instantiation of this enclave
    /// saved this data.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Return value
    ///
    /// The unsealed data in SgxUnsealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// The size of T may be zero.
    ///
    /// **SGX_ERROR_INVALID_CPUSVN**
    ///
    /// The CPUSVN in the sealed data blob is beyond the CPUSVN value of the platform.
    /// SGX_ERROR_INVALID_ISVSVN The ISVSVN in the sealed data blob is greater than the ISVSVN value of the enclave.
    ///
    /// **SGX_ERROR_MAC_MISMATCH**
    ///
    /// The tag verification failed during unsealing. The error may be caused by a platform update,
    /// software update, or sealed data blob corruption. This error is also reported if other corruption
    /// of the sealed data structure is detected.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<'a, T>> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_len = self.get_encrypt_txt_len() as usize;
        if size != encrypt_len {
            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
        }
        self.inner.unseal_data().map(|x| {
            let ptr = Box::into_raw(x.decrypt);
            SgxUnsealedData {
                payload_size: x.payload_size,
                decrypt: unsafe{Box::from_raw(ptr as *mut T)},
                additional: x.additional,
                marker: PhantomData,
            }
        })
    }

    ///
    /// Convert a pointer of sgx_sealed_data_t buffer to SgxSealedData.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **p**
    ///
    /// The mutable pointer of sgx_sealed_data_t buffer.
    ///
    /// **len**
    ///
    /// The size of the parameter `p`.
    ///
    /// # Return value
    ///
    /// **Some(SgxSealedData)**
    ///
    /// Indicates the conversion is successfully. The return value is SgxSealedData.
    ///
    /// **None**
    ///
    /// Maybe the size of T is zero.
    ///
    pub unsafe fn from_raw_sealed_data_t(p: *mut sgx_sealed_data_t, len: u32) -> Option<Self> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return None;
        }
        let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
        opt.map(|x| {
            SgxSealedData{
                inner: x,
                marker: PhantomData}
        })
    }

    ///
    /// Convert SgxSealedData to the pointer of sgx_sealed_data_t.
    ///
    /// # Parameters
    ///
    /// **p**
    ///
    /// The pointer of sgx_sealed_data_t to save the data in SgxSealedData.
    ///
    /// **len**
    ///
    /// The size of the pointer of sgx_sealed_data_t.
    ///
    /// # Error
    ///
    /// **Some(*mut sgx_sealed_data_t)**
    ///
    /// Indicates the conversion is successfully. The return value is the pointer of sgx_sealed_data_t.
    ///
    /// **None**
    ///
    /// May be the parameter p and len is not avaliable.
    ///
    pub unsafe fn to_raw_sealed_data_t(&self, p: *mut sgx_sealed_data_t, len: u32) -> Option<*mut sgx_sealed_data_t> {
        self.inner.to_raw_sealed_data_t(p, len)
    }
}

/// The encrypt_text to seal is [T], and T must have Copy and ContiguousMemory trait.
impl<'a, T: 'a + Copy + ContiguousMemory> SgxSealedData<'a, [T]> {

    ///
    /// This function is used to AES-GCM encrypt the input data. Two input data sets
    /// are provided: one is the data to be encrypted; the second is optional additional data
    /// that will not be encrypted but will be part of the GCM MAC calculation which also covers the data to be encrypted.
    ///
    /// # Descryption
    ///
    /// The seal_data function retrieves a key unique to the enclave and uses
    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret
    /// data after the enclave is destroyed. The sealed data blob can be
    /// unsealed on future instantiations of the enclave.
    /// The additional data buffer will not be encrypted but will be part of the MAC
    /// calculation that covers the encrypted data as well. This data may include
    /// information about the application, version, data, etc which can be utilized to
    /// identify the sealed data blob since it will remain plain text
    /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
    /// allocate for the `SgxSealedData` structure. The input sealed data buffer and
    /// text2encrypt buffers must be allocated within the enclave.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **additional_text**
    ///
    /// Pointer to the additional Message Authentication Code (MAC) data.
    /// This additional data is optional and no data is necessary.
    ///
    /// **encrypt_text**
    ///
    /// Pointer to the data stream to be encrypted, which is &[T]. Must be within the enclave.
    ///
    /// # Return value
    ///
    /// The sealed data in SgxSealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// Indicates an error if the parameters do not meet any of the following conditions:
    ///
    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
    /// * encrypt_text must be non-zero.
    /// * encrypt_text buffer must be within the enclave.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn seal_data(additional_text: &[u8], encrypt_text: &'a [T]) -> SgxResult<Self> {

        let size = mem::size_of::<T>();
        let len = mem::size_of_val(encrypt_text);
        if size == 0 || len == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_slice: &[u8] = unsafe {
            slice::from_raw_parts(encrypt_text.as_ptr() as *const u8, len)
        };

        let result = SgxInternalSealedData::seal_data(additional_text, encrypt_slice);
        result.map(|x| {
            SgxSealedData {
                inner: x,
                marker: PhantomData,
            }
        })
    }

    ///
    /// This function is used to AES-GCM encrypt the input data. Two input data sets
    /// are provided: one is the data to be encrypted; the second is optional additional
    /// data that will not be encrypted but will be part of the GCM MAC calculation
    /// which also covers the data to be encrypted. This is the expert mode
    /// version of function `seal_data`.
    ///
    /// # Descryption
    ///
    /// The `seal_data_ex` is an extended version of `seal_data`. It
    /// provides parameters for you to identify how to derive the sealing key (key
    /// policy and attributes_mask). Typical callers of the seal library should be
    /// able to use `seal_data` and the default values provided for key_
    /// policy (MR_SIGNER) and an attribute mask which includes the RESERVED,
    /// INITED and DEBUG bits. Users of this function should have a clear understanding
    /// of the impact on using a policy and/or attribute_mask that is different from that in seal_data.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **key_policy**
    ///
    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy.
    ///
    /// Key policy name | Value | Description
    /// ---|---|---
    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register
    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register
    ///
    /// **attribute_mask**
    ///
    /// Identifies which platform/enclave attributes to use in the key derivation. See
    /// the definition of sgx_attributes_t to determine which attributes will be
    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0.
    ///
    /// **misc_mask**
    ///
    /// The misc mask bits for the enclave. Reserved for future function extension.
    ///
    /// **additional_text**
    ///
    /// Pointer to the additional Message Authentication Code (MAC) data.
    /// This additional data is optional and no data is necessary.
    ///
    /// **encrypt_text**
    ///
    /// Pointer to the data stream to be encrypted, which is &[T]. Must not be NULL. Must be within the enclave.
    ///
    /// # Return value
    ///
    /// The sealed data in SgxSealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// Indicates an error if the parameters do not meet any of the following conditions:
    ///
    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
    /// * encrypt_text must be non-zero.
    /// * encrypt_text buffer must be within the enclave.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn seal_data_ex(key_policy: u16,
                        attribute_mask: sgx_attributes_t,
                        misc_mask: sgx_misc_select_t,
                        additional_text: &[u8],
                        encrypt_text: &'a [T]) -> SgxResult<Self> {

        let size = mem::size_of::<T>();
        let len = mem::size_of_val(encrypt_text);
        if size == 0 || len == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_slice: &[u8] = unsafe {
            slice::from_raw_parts(encrypt_text.as_ptr() as *const u8, len)
        };

        let result = SgxInternalSealedData::seal_data_ex(key_policy,
                                                         attribute_mask,
                                                         misc_mask,
                                                         additional_text,
                                                         encrypt_slice);
        result.map(|x| {
            SgxSealedData {
                inner: x,
                marker: PhantomData,
            }
        })
    }

    ///
    /// This function is used to AES-GCM decrypt the input sealed data structure.
    /// Two output data sets result: one is the decrypted data; the second is the
    /// optional additional data that was part of the GCM MAC calculation but was not
    /// encrypted. This function provides the converse of seal_data and
    /// seal_data_ex.
    ///
    /// # Descryption
    ///
    /// The unseal_data function AES-GCM decrypts the sealed data so that
    /// the enclave data can be restored. This function can be utilized to restore
    /// secret data that was preserved after an earlier instantiation of this enclave
    /// saved this data.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Return value
    ///
    /// The unsealed data in SgxUnsealedData.
    ///
    /// # Errors
    ///
    /// **SGX_ERROR_INVALID_PARAMETER**
    ///
    /// The size of T may be zero.
    ///
    /// **SGX_ERROR_INVALID_CPUSVN**
    ///
    /// The CPUSVN in the sealed data blob is beyond the CPUSVN value of the platform.
    /// SGX_ERROR_INVALID_ISVSVN The ISVSVN in the sealed data blob is greater than the ISVSVN value of the enclave.
    ///
    /// **SGX_ERROR_MAC_MISMATCH**
    ///
    /// The tag verification failed during unsealing. The error may be caused by a platform update,
    /// software update, or sealed data blob corruption. This error is also reported if other corruption
    /// of the sealed data structure is detected.
    ///
    /// **SGX_ERROR_OUT_OF_MEMORY**
    ///
    /// The enclave is out of memory.
    ///
    /// **SGX_ERROR_UNEXPECTED**
    ///
    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
    /// random number.
    ///
    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<'a, [T]>> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
        }
        let encrypt_len = self.get_encrypt_txt_len() as usize;
        if size > encrypt_len {
            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
        }
        if (encrypt_len % size) != 0 {
            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
        }

        self.inner.unseal_data().map(|x| {
            let ptr = Box::into_raw(x.decrypt);
            let slice = unsafe{slice::from_raw_parts_mut(ptr as *mut T, encrypt_len/size)};
            SgxUnsealedData {
                payload_size: x.payload_size,
                decrypt: unsafe{Box::from_raw(slice as *mut [T])},
                additional: x.additional,
                marker: PhantomData,
            }
        })
    }

    ///
    /// Convert a pointer of sgx_sealed_data_t buffer to SgxSealedData.
    ///
    /// # Requirements
    ///
    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
    ///
    /// # Parameters
    ///
    /// **p**
    ///
    /// The mutable pointer of sgx_sealed_data_t buffer.
    ///
    /// **len**
    ///
    /// The size of the parameter `p`.
    ///
    /// # Return value
    ///
    /// **Some(SgxSealedData)**
    ///
    /// Indicates the conversion is successfully. The return value is SgxSealedData.
    ///
    /// **None**
    ///
    /// Maybe the size of T is zero.
    ///
    pub unsafe fn from_raw_sealed_data_t(p: *mut sgx_sealed_data_t, len: u32) -> Option<Self> {

        let size = mem::size_of::<T>();
        if size == 0 {
            return None;
        }
        let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
        opt.map(|x| {
            SgxSealedData{
                inner: x,
                marker: PhantomData}
        })
    }

    ///
    /// Convert SgxSealedData to the pointer of sgx_sealed_data_t.
    ///
    /// # Parameters
    ///
    /// **p**
    ///
    /// The pointer of sgx_sealed_data_t to save the data in SgxSealedData.
    ///
    /// **len**
    ///
    /// The size of the pointer of sgx_sealed_data_t.
    ///
    /// # Error
    ///
    /// **Some(*mut sgx_sealed_data_t)**
    ///
    /// Indicates the conversion is successfully. The return value is the pointer of sgx_sealed_data_t.
    ///
    /// **None**
    ///
    /// May be the parameter p and len is not avaliable.
    ///
    pub unsafe fn to_raw_sealed_data_t(&self, p: *mut sgx_sealed_data_t, len: u32) -> Option<*mut sgx_sealed_data_t> {
        self.inner.to_raw_sealed_data_t(p, len)
    }
}

impl<'a, T: 'a + ?Sized> SgxSealedData<'a, T> {

    ///
    /// Create a SgxSealedData with default values.
    ///
    pub fn new() -> Self {
        SgxSealedData::default()
    }

    ///
    /// Get the size of payload in SgxSealedData.
    ///
    pub fn get_payload_size(&self) -> u32 {
        self.inner.get_payload_size()
    }

    ///
    /// Get a slice of payload in SgxSealedData.
    ///
    pub fn get_payload_tag(&self) -> &[u8; SGX_SEAL_TAG_SIZE] {
        self.inner.get_payload_tag()
    }

    ///
    /// Get the pointer of sgx_key_request_t in SgxSealedData.
    ///
    pub fn get_key_request(&self) -> &sgx_key_request_t {
        self.inner.get_key_request()
    }

    ///
    /// Get a slice of encrypt text in SgxSealedData.
    ///
    pub fn get_encrypt_txt(&self) -> &[u8] {
        self.inner.get_encrypt_txt()
    }

    ///
    /// Get a slice of additional text in SgxSealedData.
    ///
    pub fn get_additional_txt(&self) -> &[u8] {
        self.inner.get_additional_txt()
    }

    ///
    /// Calculate the size of the sealed data in SgxSealedData.
    ///
    pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32  {
        SgxInternalSealedData::calc_raw_sealed_data_size(add_mac_txt_size, encrypt_txt_size)
    }

    ///
    /// Get the size of the additional mactext in SgxSealedData.
    ///
    pub fn get_add_mac_txt_len(&self) -> u32 {
        self.inner.get_add_mac_txt_len()
    }

    ///
    /// Get the size of the encrypt text in SgxSealedData.
    ///
    pub fn get_encrypt_txt_len(&self) -> u32 {
        self.inner.get_encrypt_txt_len()
    }
}