blob: 7f8bc45ae08571e08248cd964e7367f943f3c3e7 [file] [log] [blame]
// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Baidu, Inc., nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! Trust Platform Service Functions
//!
//! The sgx_tservice library provides the following functions that allow an ISV
//! to use platform services and get platform services security property.
//!
//! This API is only available in simulation mode.
//!
use sgx_types::*;
use core::cell::Cell;
///
/// rsgx_create_pse_session creates a session with the PSE.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// An Intel(R) SGX enclave first calls rsgx_create_pse_session() in the process to request platform service.
///
/// It's suggested that the caller should wait (typically several seconds to tens of seconds) and retry
/// this API if SGX_ERROR_BUSY is returned.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_BUSY**
///
/// The requested service is temporarily not available.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UPDATE_NEEDED**
///
/// Intel(R) SGX needs to be updated.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurred.
///
pub fn rsgx_create_pse_session() -> SgxError {
let ret = unsafe { sgx_create_pse_session() };
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// rsgx_close_pse_session closes a session created by rsgx_create_pse_ session.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// An Intel(R) SGX enclave calls rsgx_close_pse_session() when there is no need to request platform service.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn rsgx_close_pse_session() -> SgxError {
let ret = unsafe { sgx_close_pse_session() };
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// rsgx_get_ps_sec_prop gets a data structure describing the security property of the platform service.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Gets a data structure that describes the security property of the platform service.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// # Parameters
///
/// **security_property**
///
/// A pointer to the buffer that receives the security property descriptor of the platform service.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
pub fn rsgx_get_ps_sec_prop(security_property: &mut sgx_ps_sec_prop_desc_t) -> SgxError {
let ret = unsafe { sgx_get_ps_sec_prop(security_property as * mut sgx_ps_sec_prop_desc_t) };
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
///
/// rsgx_get_trusted_time gets trusted time from the AE service.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// current_time contains time in seconds and time_source_nonce contains nonce associate with the time.
/// The caller should compare time_ source_nonce against the value returned from the previous call of
/// this API if it needs to calculate the time passed between two readings of the Trusted Timer. If the
/// time_source_nonce of the two readings do not match, the difference between the two readings does not
/// necessarily reflect time passed.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// # Parameters
///
/// **current_time**
///
/// Trusted Time Stamp in seconds relative to a reference point. The reference point does not change as long as
/// the time_source_nonce has not changed.
///
/// **time_source_nonce**
///
/// A pointer to the buffer that receives the nonce which indicates time source.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn rsgx_get_trusted_time(current_time: &mut sgx_time_t,
time_source_nonce: &mut sgx_time_source_nonce_t) -> SgxError {
let ret = unsafe { sgx_get_trusted_time(current_time as * mut sgx_time_t, time_source_nonce as * mut sgx_time_source_nonce_t) };
match ret {
sgx_status_t::SGX_SUCCESS => Ok(()),
_ => Err(ret),
}
}
fn rsgx_create_monotonic_counter_ex(owner_policy: u16,
owner_attribute_mask: &sgx_attributes_t,
counter_uuid: &mut sgx_mc_uuid_t,
counter_value: &mut u32) -> sgx_status_t {
unsafe {
sgx_create_monotonic_counter_ex(owner_policy,
owner_attribute_mask as * const sgx_attributes_t,
counter_uuid as * mut sgx_mc_uuid_t,
counter_value as * mut u32)
}
}
fn rsgx_create_monotonic_counter(counter_uuid: &mut sgx_mc_uuid_t, counter_value: &mut u32) -> sgx_status_t {
unsafe {
sgx_create_monotonic_counter(counter_uuid as * mut sgx_mc_uuid_t, counter_value as * mut u32)
}
}
fn rsgx_destroy_monotonic_counter(counter_uuid: &sgx_mc_uuid_t) -> sgx_status_t {
unsafe {
sgx_destroy_monotonic_counter(counter_uuid as * const sgx_mc_uuid_t)
}
}
fn rsgx_increment_monotonic_counter(counter_uuid: &sgx_mc_uuid_t, counter_value: &mut u32) -> sgx_status_t {
unsafe {
sgx_increment_monotonic_counter(counter_uuid as * const sgx_mc_uuid_t, counter_value as * mut u32)
}
}
fn rsgx_read_monotonic_counter(counter_uuid: &sgx_mc_uuid_t, counter_value: &mut u32) -> sgx_status_t {
unsafe {
sgx_read_monotonic_counter(counter_uuid as * const sgx_mc_uuid_t, counter_value as * mut u32)
}
}
/// Monotonic counter ID
pub struct SgxMonotonicCounter {
counter_uuid: sgx_mc_uuid_t,
initflag: Cell<bool>,
}
impl SgxMonotonicCounter {
///
/// creates a monotonic counter with default owner policy and default user attribute mask.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Call new to create a monotonic counter with the default owner policy 0x1, which means enclaves
/// with same signing key can access the monotonic counter and default owner_attribute_mask 0xFFFFFFFFFFFFFFCB.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
/// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
/// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed
/// the limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
///
/// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota,
/// an SGX application should record the MC UUID that rsgx_create_monotonic_counter returns and destroy a MC
/// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not
/// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again.
/// This procedure deletes all MCs created by any enclave in that system.
///
/// # Parameters
///
/// **counter_value**
///
/// A pointer to the buffer that receives the monotonic counter value.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Return value
///
/// Monotonic counter ID
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_BUSY**
///
/// The requested service is temporarily not available.
///
/// **SGX_ERROR_MC_OVER_QUOTA**
///
/// The enclave has reached the quota of Monotonic Counters it can maintain.
///
/// **SGX_ERROR_MC_USED_UP**
///
/// Monotonic counters are used out.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn new(counter_value: &mut u32) -> SgxResult<Self> {
let mut counter_uuid = sgx_mc_uuid_t::default();
let ret = rsgx_create_monotonic_counter(&mut counter_uuid, counter_value);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(SgxMonotonicCounter{counter_uuid: counter_uuid, initflag: Cell::new(true)}),
_ => Err(ret),
}
}
///
/// creates a monotonic counter.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Call new_ex to create a monotonic counter with the given owner_policy and owner_attribute_mask.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
/// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
/// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed
/// the limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
///
/// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota,
/// an SGX application should record the MC UUID that rsgx_create_monotonic_counter_ex returns and destroy a MC
/// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not
/// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again.
/// This procedure deletes all MCs created by any enclave in that system.
///
/// # Parameters
///
/// **owner_policy**
///
/// The owner policy of the monotonic counter.
///
/// * 0x1 means enclave with same signing key can access the monotonic counter
/// * 0x2 means enclave with same measurement can access the monotonic counter
/// * 0x3 means enclave with same measurement as well as signing key can access the monotonic counter.
/// * Owner policy values of 0x0 or any bits set beyond bits 0 and 1 will cause SGX_ERROR_INVALID_PARAMETER
///
/// **owner_attribute_mask**
///
/// Mask of owner attribute, in the format of sgx_attributes_t.
///
/// **counter_value**
///
/// A pointer to the buffer that receives the monotonic counter value.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Return value
///
/// Monotonic counter ID
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_BUSY**
///
/// The requested service is temporarily not available.
///
/// **SGX_ERROR_MC_OVER_QUOTA**
///
/// The enclave has reached the quota of Monotonic Counters it can maintain.
///
/// **SGX_ERROR_MC_USED_UP**
///
/// Monotonic counters are used out.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn new_ex(owner_policy: u16, owner_attribute_mask: &sgx_attributes_t, counter_value: &mut u32) -> SgxResult<Self> {
let mut counter_uuid = sgx_mc_uuid_t::default();
let ret = rsgx_create_monotonic_counter_ex(owner_policy, owner_attribute_mask, &mut counter_uuid, counter_value);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(SgxMonotonicCounter{counter_uuid: counter_uuid, initflag: Cell::new(true)}),
_ => Err(ret),
}
}
///
/// destroys a monotonic counter created by new or new_ex.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Calling destory after a monotonic counter is not needed anymore.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// destory fails if the calling enclave does not match the owner policy and the attributes specified in the
/// call that created the monotonic counter.
///
/// Destroying a Monotonic Counter (MC) involves writing to the non-volatile memory available in the platform.
/// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
/// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the
/// limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_BUSY**
///
/// The requested service is temporarily not available.
///
/// **SGX_ERROR_MC_NOT_FOUND**
///
/// The Monotonic Counter does not exist or has been invalidated.
///
/// **SGX_ERROR_MC_NO_ACCESS_RIGHT**
///
/// The enclave doesn't have the access right to specified Monotonic Counter.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn destory(&self) -> SgxError {
if self.initflag.get() == false {
return Err(sgx_status_t::SGX_ERROR_MC_NOT_FOUND);
}
let ret = rsgx_destroy_monotonic_counter(&self.counter_uuid);
if ret == sgx_status_t::SGX_SUCCESS {
self.initflag.set(false);
Ok(())
} else {
Err(ret)
}
}
///
/// increments a monotonic counter value by 1.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Call increment to increase a monotonic counter value by 1.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// increment fails if the calling enclave does not match the owner policy and the attributes specified in the
/// call that created the monotonic counter.
///
/// Incrementing a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
/// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
/// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the limit,
/// the MC operation may return SGX_ERROR_BUSY for several minutes.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_BUSY**
///
/// The requested service is temporarily not available.
///
/// **SGX_ERROR_MC_NOT_FOUND**
///
/// The Monotonic Counter does not exist or has been invalidated.
///
/// **SGX_ERROR_MC_NO_ACCESS_RIGHT**
///
/// The enclave doesn't have the access right to specified Monotonic Counter.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn increment(&self) -> SgxResult<u32> {
if self.initflag.get() == false {
return Err(sgx_status_t::SGX_ERROR_MC_NOT_FOUND);
}
let mut counter_value: u32 = 0;
let ret = rsgx_increment_monotonic_counter(&self.counter_uuid, &mut counter_value);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(counter_value),
_ => Err(ret),
}
}
///
/// returns the value of a monotonic counter.
///
/// This API is only available in simulation mode.
///
/// # Description
///
/// Call read to read the value of a monotonic counter.
///
/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
/// before calling this API.
///
/// read fails if the calling enclave does not match the owner policy and the attributes specified in the
/// call that created the monotonic counter.
///
/// # Requirements
///
/// Header: sgx_tae_service.edl
///
/// Library: libsgx_tservice_sim.a (simulation)
///
/// # Return value
///
/// Monotonic counter value
///
/// # Errors
///
/// **SGX_ERROR_INVALID_PARAMETER**
///
/// Any of the pointers is invalid.
///
/// **SGX_ERROR_MC_NOT_FOUND**
///
/// The Monotonic Counter does not exist or has been invalidated.
///
/// **SGX_ERROR_AE_SESSION_INVALID**
///
/// Session is not created or has been closed by architectural enclave service.
///
/// **SGX_ERROR_SERVICE_UNAVAILABLE**
///
/// The AE service did not respond or the requested service is not supported.
///
/// **SGX_ERROR_SERVICE_TIMEOUT**
///
/// A request to the AE service timed out.
///
/// **SGX_ERROR_NETWORK_FAILURE**
///
/// Network connecting or proxy setting issue was encountered.
///
/// **SGX_ERROR_OUT_OF_MEMORY**
///
/// Not enough memory is available to complete this operation.
///
/// **SGX_ERROR_OUT_OF_EPC**
///
/// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
///
/// **SGX_ERROR_UNEXPECTED**
///
/// Indicates an unexpected error occurs.
///
pub fn read(&self) -> SgxResult<u32> {
if self.initflag.get() == false {
return Err(sgx_status_t::SGX_ERROR_MC_NOT_FOUND);
}
let mut counter_value: u32 = 0;
let ret = rsgx_read_monotonic_counter(&self.counter_uuid, &mut counter_value);
match ret {
sgx_status_t::SGX_SUCCESS => Ok(counter_value),
_ => Err(ret),
}
}
}
impl Drop for SgxMonotonicCounter {
///
/// destroys a monotonic counter created by new or new_ex.
///
fn drop(&mut self) {
let _ = self.destory();
}
}