Drop the litemap and zerofrom pins
The two
=pins were added when the MSRV was 1.71. The MSRV is 1.94.1 now and the crate does not use either directly.The litemap pin had become a dead duplicate: the icu crates already require litemap 0.8, so
=0.7.4only added an unused second copy to the build. The zerofrom pin held the icu tree at 2.1, because icu 2.3 requires zerofrom 0.1.6.Update both README MSRV badges from 1.71.1 to 1.94.1 to match rust-version in Cargo.toml.
Signed-off-by: Mushahid Hussain (Kiro) hmushi@amazon.co.uk
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
aws-nitro-enclaves-image-format
This library provides the definition of the enclave image format (EIF) file.
Security
See CONTRIBUTING for more information.
License
This project is licensed under the Apache-2.0 License.
Enclave Image File (EIF) Specification
Date: 2024-06-21
Background
AWS Nitro Enclaves (Official documentation) is an Amazon EC2 feature that allows you to create isolated compute environments, called enclaves, from Amazon EC2 instances. Enclaves are separate, hardened, and highly-constrained virtual machines. They provide only secure local socket connectivity with their parent instance. They have no persistent storage, interactive access, or external networking.
To run your application in an enclave, your application needs to be packaged into an Enclave Image File (EIF). An EIF is self contained - everything your application needs to run within an enclave is part of the file (e.g. operating system, your application, root file system).
The File Format
High Level Structure
On a high level an Enclave Image File consists of a general header and multiple data sections, each with their local header:
The Enclave Image File format supports a variety of data section types. The data section types can be mandatory or optional. Each section contains a specific type of data needed to run your application within a Nitro Enclave, the specifics of which are specified below in Data sections.
EifHeaderThe
EifHeaderis a general description of an enclave image file and provides metadata on the file as a whole. It has a fixed size of 548 bytes and the byte-order for all multi-byte fields is big-endian. TheEifHeaderis structured as follows:All reserved fields are ignored by the virtualization stack.
magicThe
magicfield is a constant value chosen to easily identify enclave image files. The value equates to the ASCII string.eifor[0x2e, 0x65, 0x69, 0x66]as byte array.versionThe
versionfield encodes the specification version of the enclave image file. It is necessary to determine the file format version and chose the correct handling according to it.The latest version of the EIF format is
4. The version gets incremented whenever a backwards incompatible change or addition to the file format is introduced.EIF format version history:
0: internal development version1: internal development version2: initial publicly released version as published in aws-nitro-enclaves-cli v0.1.0 (initial public pre-release) on 2020-08-13. This initial version set the basic file format structure and supported the base section typesEifSectionKernel,EifSectionCmdline, andEifSectionRamdisk.3: published in aws-nitro-enclaves-cli v1.0.10 (initial public production release) on 2021-04-29. This version added optional support for image signing through section typeEifSectionSignature.4: published in aws-nitro-enclaves-cli v1.2.0 on 2022-03-08. This version added a new mandatory section typeEifSectionMetadatacontaining metadata about the environment the EIF was built in.Versions
0and1have not been published as part of any tooling release. They are not supported anymore and will fail at the crc check stage of loading the enclave image file.Versions
2and3both behave the same way. As theEifSectionSignaturesection type has not been defined in version2and is optional in version3they are effectively handled the same.Version
4introduced theEifSectionMetadataas a mandatory section and checks that it is part of an enclave image file. Apart from that it is handled the same way as Version3.Versions
>4are reserved for the future and yield undefined behavior.flagsThe
flagsbit-field encodes properties for the file and the environment the file is targeted for. The structure of the flags field is as follows:arch: determines the CPU architecture of the enclave this image file is for:0forx86_64,1foraarch64. This flag is mandatory and an EIF with an architecture other than the architecture of the enclave will be rejected.default_memThe
default_memfield describes the default amount of main memory in bytes for the enclave this image is going to run on. Currently this field is unused by the virtualization stack and aws-nitro-enclaves-cli.default_cpusThe
default_cpusfield describes the default number of vCPUs for the enclave this image is going to run on. Currently this field is unused by the virtualization stack and aws-nitro-enclaves-cli.num_sectionsThe
num_sectionsfield describes how many data sections an enclave image file contains. The value range for this is between 2 and 32 (MAX_NUM_SECTIONS).section_offsetsThe
section_offsetsfield is an array of 32 (MAX_NUM_SECTIONS) 8-byte values. The firstnum_secionsentries in this array each describe the position of one data section within the file in bytes from the file start. All used entries have to be ordered in the same order as the corresponding data sections in the file, meaningsection_offsets[0]describes the file offset for the first data section in the file,section_offset[1]describes the file offset for the second data section in the file and so on.section_sizesThe
section_sizesfield is an array of 32 (MAX_NUM_SECTIONS) 8-byte values. The firstnum_sectionsentries in this array each describe the size of one data section within the file in bytes. All used entries have to be ordered in the same order as the corresponding data sections in the file, meaningsection_sizes[0]describes the size of the first data section in the file,section_sizes[1]describes the size of the second data section in the file and so on. Thesection sizesas set in this array only cover the size of the data in a section and do not include the size of section headers.eif_crc32The
eif_crc32field contains the crc32 checksum over the whole file except thiseif_crc32field itself; this checksum includesEifHeaderand all sections, including their respective section headers, in the order they appear in the file.Data sections
An enclave image file contains multiple data sections of different types, each with a distinct purpose. The high level format is common between all section types, consisting of an
EifSectionHeaderand binary data. Sections cannot overlap each other and must not overflow out of 64-bit address space.The ordering of the different section types within one enclave image file is mostly unconstrained. The only constraint on ordering the sections is that all
EifSectionRamdisksections must be located after theEifSectionKernelsection.EifSectionHeaderThe section header is a basic description of a section:
section_typeThe
section_typefield describes the kind of section. The following is a list of valid section types and their numeric value. A detailed description of each section type follows below.EifSectionInvalid (0x00)EifSectionKernel (0x01)EifSectionCmdline (0x02)EifSectionRamdisk (0x03)EifSectionSignature (0x04)(introduced in version 3 of the EIF format)EifSectionMetadata (0x05)(introduced in version 4 of the EIF format)Enclave image files containing an
EifSectionInvalidsection or sections with a type outside of the above range (>= 6) will be rejected by the virtualization stack.flagsThe
flagsbit-field can be used to encode properties of the binary data in a section. It is currently not used by any section type and is reserved for future use.section_sizeThe
section_sizefield describes the size in bytes of the sections data. It must match the corresponding section_sizes entry in the global EifHeader structure.EifSectionKernelThe
EifSectionKernelsection data contains a Linux kernel image to be run within the enclave. The file format for that depends on the CPU architecture of your instance and its enclave. Forx86_64instances the kernel section data has to be abzImage(Refer to thex86_64boot protocol for details). Foraarch64instances the kernel section data has to be an uncompressed kernelImagefile (Refer to thearm64boot protocol for details).The aws-nitro-enclaves-cli provides pre-built kernel images for both architectures:
x86_64:blobs/x86_64/bzImageaarch64:blobs/aarch64/ImageEifSectionKernelsection is a mandatory section and every enclave image file must contain exactly oneEifSectionKernelsection.EifSectionCmdlineThe
EifSectionCmdlinesection data contains a string with Linux kernel cmdline parameters for the enclave kernel. The kernel cmdline can be used to configure certain aspects of the kernel at boot time (Documentation of kernel-parameters).The aws-nitro-enclaves-cli provides kernel cmdlines for both architectures (compatible with the pre-built kernel images in the same location):
x86_64:blobs/x86_64/cmdlineaarch64:blobs/aarch64/cmdlineEifSectionCmdlinesection is a mandatory section and every enclave image file must contain exactly oneEifSectionCmdlinesection.EifSectionRamdiskThe
EifSectionRamdisksection contains data that is going to be part of the root file system of the enclave incpioorcpio.gz(compressed) format. All data ofEifSectionRamdisksections are concatenated to act together as oneinitramfs(See Background on ramdisk composition and loading below).All
EifSectionRamdisksections must be positioned after theEifSectionKernelsection within an enclave image file.Example: ramdisks created with aws-nitro-enclaves-cli
When creating an enclave image file through the aws-nitro-enclaves-cli, two
EifSectionRamdisksections are created. The first ramdisk is the same for all applications and contains two main parts:x86_64:blobs/x86_64/initaarch64:blobs/aarch64/initnsm.kodriver: This is a loadable driver module for the Linux kernel which facilitates access to the Nitro Secure Module (NSM). The driver exposes a special device in the enclave to communicate with the hypervisor to retrieve an attestation document, which can be used to prove the identity of the enclave. The source code for the NSM driver can be found in aws-nitro-enclaves-sdk-bootstrap, starting with Linux kernel series v6.8 the driver is part of the upstream Linux kernel. The aws-nitro-enclaves-cli provides pre-compiled versions of this driver for both architectures (compatible with the pre-built kernel images in the same location):x86_64:blobs/x86_64/nsm.koaarch64:blobs/aarch64/nsm.koThe second ramdisk contains the application specific data and has three major parts:
cmdfile: Thecmdfile contains the default entry point of the application as specified in the Dockerfile throughCMD(orENTRYPOINTifCMDis not specified).envfile: Theenvfile contains the environment variables of the application as specified in the Dockerfile throughENV.Background on ramdisk composition and loading
The Linux kernel supports various models of booting a system and bringing up user-space. One mechanism is through the Linux kernel’s
initramfsformat (See Linux kernel documentationdriver-api/early-userspace/buffer-format.rst). Aninitramfsconsists of a collection ofcpiofiles, either uncompressed (.cpio) or compressed (.cpio.gz). The Linux kernel contains a minimal interpreter for these files to loadinitramfsand construct the root file system from them. Theinitramfsusually contains a basic user-space to bootstrap a system and bring up additional devices like hard disks to switch to the final file system from disk. In the case of Nitro Enclaves, there is no support for persistent storage like hard disks, so the whole system is booted from and contained in the initramfs.For Nitro Enclaves, no bootloader is employed to load the kernel and ramdisks into memory. That part is performed by the hypervisor, which loads the kernel and ramdisk data into the enclaves memory before starting the enclave. The resulting enclave memory on startup is populated as follows from the EIF (For an example EIF with three ramdisk sections):
EifSectionSignatureThe
EifSectionSignaturesection was introduced as an optional section in file format version 3. The section data has a maximum size of 32768 bytes (SIGNATURE_MAX_SIZE).The data format for the
EifSectionSignaturesection is Concise Binary Object Representation (CBOR) as introduced in RFC8949. The CBOR data contains an array of two-tuples, each containing a serialized signing certificate and a serialized CBOR Object Signing and Encryption (COSE) Sign1 object as described in RFC8152. Although theEifSectionSignaturesection allows for multiple such tuples, only the first of these objects is currently verified against PCR0. This means the only relevant data to sign and add to theEifSectionSignaturesection is the tuple(0, PCR0).The overall structure of the CBOR data in
EifSectionSignaturecan be described as follows, where>>>>and<<<<describe entry and exit boundaries of nested serialized CBOR data:Background on COSE Sign1 and usage in EIF
COSE Sign1 provides a signature structure to have a message signed by a single signer:
The COSE Headers are divided into two buckets, the protected bucket contains metadata for the signature layer that is part of the data being signed (covered/protected by the signature), while the unprotected bucket contains metadata that does not contribute towards the signature. Each bucket is a map of key-value pairs. The payload is the plaintext data that is being signed. The signature contains the signature bytes.
For the usage in EIF the data contained in the different parts of the COSE Sign1 object is as follows:
EifSectionMetadataThe
EifSectionMetadatasection was introduced as a mandatory section in file format version 4. The section data contains JSON describing the build environment that produced the enclave image file according to the following JSON schema:The
EifSectionMetadatasection is not part of any measurement for an enclave and does not get validated by the hypervisor, beyond checking for its existence with file format version 4 and above.EIF Measurements
Nitro Enclaves includes attestation mechanisms to prove its identity and build trust with external services. As part of these measurements the enclave exposes a set of platform configuration registers (PCRs), each providing a set of hashes over some identifying data for the enclaves configuration and code. For the EIF files, there are four PCRs that describe it. They are
PCR0,PCR1,PCR2, andPCR8:All EIF specific PCRs are calculated in a multi-level scheme containing a fixed initial state and a digest over specific parts of the EIF. They are calculated as the sha384 message digest (described in RFC6234) over the concatenation of the
initial_digestand thecontent_digest:The
initial_digestis the same for all PCRs and consists of 48 zero-bytes. Thecontent_digestcontains data on different parts of an EIF depending on the PCR.PCR0PCR0contains a measurement of all the data influencing the runtime of code in an EIF. It includes a sha384 message digest over the contiguous data of theEifSectionKernel,EifSectionCmdline, and allEifSectionRamdisksections in the order they are present in the enclave image file. ForPCR0this meanscontent_digestis calculated as follows:Note: The order of elements in that calculation depends on the order of sections in the EIF. Only the data for each section is part of the calculation, the headers are excluded.
PCR1PCR1contains a measurement of all the data influencing the bootstrap and kernel in an EIF. It includes a sha384 message digest over the contiguous data of theEifSectionKernel,EifSectionCmdline, and the firstEifSectionRamdisksections in the order they are present in the enclave image file. ForPCR1this meanscontent_digestis calculated as follows:Note: The order of elements in that calculation depends on the order of sections in the EIF. Only the data for each section is part of the calculation, the headers are excluded.
PCR2PCR2contains a measurement of the user application in an EIF. It includes a sha384 message digest over the contiguous data of allEifSectionRamdisksections excluding the firstEifSectionRamdisksection in the order they are present in the enclave image file. ForPCR2this meanscontent_digestis calculated as follows:Note: The order of elements in that calculation depends on the order of sections in the EIF. Only the data for each section is part of the calculation, the headers are excluded.
PCR8PCR8is populated only if anEifSectionSignaturesection is part of the enclave image file. In that casePCR8contains a measurement over the DER representation of the certificate used to signPCR0and contained inEifSectionSignature. ForPCR8this meanscontent_digestis calculated as follows: