// 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
//!
//! The library 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.
//! * Provides APIs to authenticate and verify the input data with AES-GMAC.
//!
//! The library also provides APIs to help calculate the sealed data size, encrypt text length, and Message Authentication Code (MAC) text length.
//!
//! # Description
//!
//! When an enclave is instantiated, it provides protections (confidentiality and
//! integrity) to the data by keeping it within the boundary of the enclave. Enclave
//! developers should identify enclave data and/or state that is considered secret
//! and potentially needs preservation across the following enclave destruction
//! events:
//!
//! * Application is done with the enclave and closes it.
//! * Application itself is closed.
//! * The platform is hibernated or shutdown.
//!
//! In general, the secrets provisioned within an enclave are lost when the enclave
//! is closed. However if the secret data needs to be preserved during one of
//! these events for future use within an enclave, it must be stored outside the
//! enclave boundary before closing the enclave. In order to protect and preserve
//! the data, a mechanism is in place which allows enclave software to retrieve a
//! key unique to that enclave. This key can only be generated by that enclave on
//! that particular platform. Enclave software uses that key to encrypt data to the
//! platform or to decrypt data already on the platform. Refer to these encrypt
//! and decrypt operations as sealing and unsealing respectively as the data is
//! cryptographically sealed to the enclave and platform.
//!
//! To provide strong protection against potential key-wear-out attacks, a unique
//! seal key is generated for each data blob encrypted with the seal_data
//! API call. A key ID for each encrypted data blob is stored in clear alongside the
//! encrypted data blob. The key ID is used to re-generate the seal key to decrypt
//! the data blob.
//!
//! AES-GCM (AES – Advanced Encryption Standard) is utilized to encrypt and
//! MAC-protect the payload. To protect against software-based side channel
//! attacks, the crypto implementation of AES-GCM utilizes AES-NI, which is
//! immune to software-based side channel attacks. The Galois/Counter Mode
//! (GCM) is a mode of operation of the AES algorithm. GCM assures authenticity
//! of the confidential data (of up to about 64 GB per invocation) using a universal
//! hash function. GCM can also provide authentication assurance for additional
//! data (of practically unlimited length per invocation) that is not encrypted. GCM
//! can also provide authentication assurance for additional data (of practically
//! unlimited length per invocation) that is not encrypted. If the GCM input contains
//! only data that is not to be encrypted, the resulting specialization of GCM,
//! called GMAC (Galois Message Authentication Code), is simply an authentication
//! mode for the input data. The mac_aadata API call restricts the input to
//! non-confidential data to provide data origin authentication only. The single
//! output of this function is the authentication tag.
//!

#![no_std]
#![cfg_attr(
    all(target_env = "sgx", target_vendor = "mesalock"),
    feature(rustc_private)
)]

#![allow(non_camel_case_types)]
#![allow(unused_assignments)]
#![allow(clippy::missing_safety_doc)]

#[macro_use]
extern crate alloc;

extern crate sgx_tcrypto;
extern crate sgx_trts;
extern crate sgx_tse;
extern crate sgx_types;

mod seal;
pub use self::seal::{SgxSealedData, SgxUnsealedData};

mod aad;
pub use self::aad::SgxMacAadata;

mod internal;
