Warning:
this component has no documented requirements. A new requirements page should be created and linked to this component.
Contents |
The AWS Nitro TEE Verifier contract is a smart contract responsible for verifying the attestation document generated by an AWS Nitro Enclave, ensuring the integrity and authenticity of the enclave’s execution environment. An AWS Nitro Enclave, also referred to as an AWS Nitro TEE, is a secure, isolated execution environment embedded within an Amazon EC2 instance. Each enclave operates as a separate virtual machine with its own kernel, memory, and virtual CPUs, isolated from the parent EC2 instance by the AWS Nitro Hypervisor. This isolation ensures that even the parent instance’s root user, as well as its processes and applications, cannot access the enclave’s memory or vCPUs. Enclaves lack external networking, persistent storage, and interactive access (e.g., SSH), as their memory is allocated from the parent instance’s RAM and is not persisted. The only communication channel between the enclave and its parent instance is a secure local socket known as a virtual socket (vsock), which enables data exchange while maintaining isolation.
The registerSigner function registers a new trusted signer, represented by an ephemeral ECDSA key pair generated at the application’s startup. It validates the attestation document, which includes the ephemeral public key and the Platform Configuration Register (PCR) 0 value — a cryptographic hash of the enclave’s software state that ensures the enclave is running the expected, untampered code. After verifying the attestation’s authenticity and confirming the PCR0 value matches a trusted hash, the function computes the keccak hash of the public key, converts to an ethereum adress, and then registers the trusted signer.
The function works as follows:
Calls the validateAttestation function to verify the COSE_Sign1 (CBOR Object Signing and Encryption) signature of the CBOR (Concise Binary Object Representation) - encoded attestation document, which the enclave requests from the AWS Nitro Hypervisor, ensuring the document’s authenticity using the AWS Nitro Enclave’s cryptographic root of trust.
After the verification is successful we extract the PCR0, compute the keccak256 hash, and verify that the PCR0 value is in the registeredEnclaveHash.
Next, we extract the ephemeral public key which we used to retrieve the attesation from the enclave, compute the keccak256 hash, then convert it to an address and register the signer
Finally, emit an event that the signer has been registered for the given PCR0 hash.
1 function registerSigner(attestation,signature) 2 { 3 Ptrs memory ptrs = validateAttestation(attestation, signature); 4 bytes32 pcr0 = keccak256(ptrs.pcrs[0]); 5 // Verify pcr0 hash 6 if (!registeredEnclaveHash[pcr0]) { 7 revert InvalidEnclaveHash(); 8 } 9 10 // Retrieve the public key from the attestation 11 // We ignore first byte this just tells us if public key is compressed or not 12 bytes32 publicKeyHash = keccak256( 13 ptrs.publicKey.start() + 1, 14 ptrs.publicKey.length() - 1 15 ); 16 17 address signer = address(uint160(uint256(publicKeyHash))); 18 19 // Mark the signer as registered 20 if (!registeredSigners[signer]) { 21 registeredSigners[signer] = true; 22 emit SignerRegistered(signer, pcr0); 23 } 24 }
This function will either set or unset the PCR0 hash in the contract. Note: This will be an owner only function.
1 function setEnclaveHash(pcr0Hash, valid) 2 { 3 registeredEnclaveHash[pcr0Hash] = valid; 4 emit EnclaveHashSet(pcr0Hash, valid); 5 }
This function removes a specified set of signers from the registered signers mapping. Note: This is an owner-only function. This function is crucial in cases where an enclave hash is identified as belonging to a potentially vulnerable enclave. In such situations, we can use it to remove all signers associated with that enclave hash. The signers linked to a particular enclave hash can be determined by querying the emitted logs from the ‘registerSigner‘ function.
1 function deleteRegisteredSigners(signers) 2 { 3 for (uint i = 0; i < signers.length; i++) { 4 if (registeredSigners[signers[i]]) { 5 registeredSigners[signers[i]] = false; 6 emit SignerDeleted(signers[i]); 7 } 8 } 9 }