aws / aws-nitro-enclaves-sdk-c

This repo provides a C API for AWS Nitro Enclaves, including a KMS SDK that integrates it with attestation.
Apache License 2.0
99 stars 75 forks source link

Question: How does the plaintext after KMS decryption get back into the enclave? #51

Closed blmalone closed 3 years ago

blmalone commented 3 years ago

I've been able to provision an EC2 instance with the Nitro Enclave sample running successfully.

After spending some time reading through the code, I'd like to piece together how KMS knows to decrypt the ciphertext and return the plaintext.

The sample application has two parts, kmstool-enclave and kmstool-instance.

Of course, after encrypting data X to key Y (stored in KMS), we will want to decrypt X with Y only by the enclave. I'm aware that this is enforced by the KMS CMK policy (by providing the value of PCR0).

What isn't clear to me is that when I run the following:

# Run docker with network host to allow it to fetch IAM credentials with IMDSv2
docker run --network host -it kmstool-instance \
    /kmstool_instance --cid "$ENCLAVE_CID" --region "$CMK_REGION" "$CIPHERTEXT"

for decryption, how does the enclave actually:

  1. Establish a secure channel with KMS
  2. Securely retrieve the plaintext from KMS, I'm basing this on the assumption that all cryptographic operations happen within CloudHSM and decryption is not occurring in the enclave itself.

(My guess is that there is some attestation happening beforehand that is abstracted away? Allowing for a session to be established between enclave and KMS.)

Extra Notes:

From attestation documentation:

The Nitro Enclaves SDK includes some APIs (kms-decrypt, kms-generate-data-key, and kms-generate-random) that integrate with AWS KMS. When these APIs are called against a specific key, the enclave's attestation document, which includes its measurements, is attached to the request. AWS KMS receives the request and validates the measurements in the provided attestation document against the measurements specified in the condition keys of the CMK policy. It uses this information to determine whether the enclave should be granted permission to perform the requested action using the requested CMK.

Thanks in advance.

blmalone commented 3 years ago

@petreeftime Tagging you as you seem to be actively replying to recent issues.

richardfan1126 commented 3 years ago

@blmalone

The API call between the enclave and KMS is using HTTPS, so the data in transit is encrypted.

In addition, when kmstool-enclave generates the attestation document, it attaches its public key (enclave public key) to it. The workflow is as follow (Ref: https://docs.aws.amazon.com/enclaves/latest/user/flow.html#attest-decrypt):

  1. kmstool-enclave generate RSA keypair and attach the public key (enclave public key) to the attestation document
  2. KMS decrypt the original ciphertext (ciphertext 1) using its key (KMS key)
  3. KMS encrypt the plaintext using enclave public key (Let's call the encrypted data as ciphertext 2)
  4. KMS Send the ciphertext 2 back to the enclave
  5. kmstool-enclave uses its private key to decrypt ciphertext 2 and get the plaintext

As long as the enclave private key doesn't go out of the enclave, even an attacker cracks the HTTPS encryption and gets the KMS response, he/she still cannot get the original plaintext.

If you take a look at the code, you will find it generating RSA keypair, putting the public key to the attestation document, and decrypting KMS response using the keypair:

I've created a sample project using Python to demonstrate the entire process, you can take a look and it may help you understand:

blmalone commented 3 years ago

@richardfan1126 Thank you, great explanation.