Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Recipient field on KMS calls for Nitro Enclaves Attestation #2271

Closed
shanecurran opened this issue Jan 13, 2021 · 9 comments
Closed
Labels
closed-for-staleness feature-request This issue requests a feature. response-requested Waiting on additional info and feedback. service-api This issue is caused by the service API, not the SDK implementation.

Comments

@shanecurran
Copy link

Describe the bug
AWS Nitro Enclaves includes an attestation flow which is closely linked with KMS, whereby the response of a KMS Decrypt, GenerateRandom or GenerateDataKey encrypt the response data with a public key included in the Attestation Document. The flow is described here.

Expected behavior
There is no official documentation for this particular flow and I have had to rely on unofficial sources, such as this blog post to find out what the payload structure is. No AWS SDKs currently support the additional Recipient parameter and I have had to resort to building my own signing scheme to call the KMS endpoints directly over HTTP.

Example structure

{        
    CiphertextBlob: Base64(Bytes)
    Recipient: {
            KeyEncryptionAlgorithm: 'RSAES_OAEP_SHA_1' || 'RSAES_OAEP_SHA256' || 'SYMMETRIC_DEFAULT',
            AttestationDocument: Base64(Bytes)
    }
}
@shanecurran shanecurran added the needs-triage This issue or PR still needs to be triaged. label Jan 13, 2021
@swetashre
Copy link
Contributor

@shanecurran - Thank you for your post. I am trying to understand the issue here. You are trying to call the kms Decrypt api here with the Recipient parameter ? Can't you specify the AttestationDocument inside EncryptionContext.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kms.html#KMS.Client.decrypt
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context

AWS KMS allows you to use attestation document values in conditions keys to grant access to specific cryptographic operations.
I found this documentation which might helps:
https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms
https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-nitro-enclaves

Let me know if i misunderstood anything here.

@swetashre swetashre self-assigned this Jan 14, 2021
@swetashre swetashre added guidance Question that needs advice or information. closing-soon and removed needs-triage This issue or PR still needs to be triaged. labels Jan 14, 2021
@shanecurran
Copy link
Author

shanecurran commented Jan 14, 2021

Thanks for the response @swetashre. In the current structure of the KMS + Nitro Enclaves flow, the Recipient parameter is actually a separate field in the JSON body that gets sent to KMS on Decrypt, GenerateRandom and GenerateDataKey. It is not a field in the EncryptionContext, presumably because it is also supported by asymmetric CMKs.

KMS supports a (currently) undocumented flow whereby the resulting plaintext/random value gets RSAES_OAEP_PKCS1 encrypted using the Nitro Enclave public key from the AttestationDocument as the receiver. KMS generates a response which is PKCS#7/CMS + Base64 encoded, and included in the CiphertextForRecipient response field.

I can't find this functionality documented anywhere in the official AWS docs, which has been a source of confusion for me as I only managed to find out the request structure by reading a third-party blog. We use the functionality in production and can confirm that it works as intended.

@swetashre swetashre added the service-api This issue is caused by the service API, not the SDK implementation. label Jan 15, 2021
@kdaily
Copy link
Member

kdaily commented Feb 16, 2021

Thanks for the information @shanecurran. I've contacted the KMS team to find out more.

@kdaily
Copy link
Member

kdaily commented Feb 16, 2021

0550741557

@kdaily kdaily added feature-request This issue requests a feature. and removed guidance Question that needs advice or information. labels Feb 16, 2021
@kdaily
Copy link
Member

kdaily commented Feb 18, 2021

I heard back with from a Nitro Enclaves engineer. The documentation for this feature is here, and is complete with respect to what can be done by customers with the Recipient field, which is used internally as a "private API" to enable users of the Nitro Enclave SDK to gain access to encrypted data:

https://docs.aws.amazon.com/enclaves/latest/user/kms.html

Full description of this from the team:

The Nitro Enclaves SDK includes the Recipient field on KMS calls for the purpose of re-encrypting a ciphertext previously encrypted by the customer under an AWS KMS customer managed to be encrypted under a public key that corresponds to a private key that is 100% managed by the EC2 service in the Nitro Enclave. Therefore, it's not possible for a customer to use the Recipient field on KMS calls and insert their own arbitrary content in the request (e.g. a public key to be used for re-encryption, or an attestation document signed by some private key the customer provides). The mental model here is that the Recipient field for KMS can only be used by the the Nitro Enclave SDK and it's "hard coded" to use values that are controlled by AWS.

If there is something missing from the documentation such that this is unclear, let us know and I will relay that to the team.

@kdaily kdaily added the response-requested Waiting on additional info and feedback. label Feb 18, 2021
@github-actions
Copy link

Greetings! It looks like this issue hasn’t been active in longer than a week. We encourage you to check if this is still an issue in the latest release. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one.

@sphw
Copy link

sphw commented Mar 13, 2021

I noticed this issue was closed due to inactivity, but this is still a feature that I think many users can benefit from. The definitions included in botocore are used to generate code for other languages libraries. For instance, Rusoto, the de-facto Rust AWS library, generates lots of its code from botocore. So to use Rusoto with these features, we have to fork botocore and Rusoto. Up-streaming our changes would be fantastic.

I understand if there is hesitancy to expose this feature to end users, but not exposing it forces people to reverse engineer the APIs based on the Nitro C SDK, and various blog posts like the one linked above. In addition, the documentation on Nitro is currently lacking. There is value in adding these docs just to elucidate how Nitro works internally.

@ChrisGreenaway
Copy link

@kdaily - so are you saying that all access to the KMS API that uses attestation has to go via the C API? What if I want an implementation native to the programming language so as to avoid an FFI call to C and the complexity of deploying C libs?

Wouldn't it be possible to generate the attestation (via interacting with the NSM device) and then attach that to a REST KMS API call using the Recipient key? So, for example, I could use https://github.com/donkersgoed/aws-nsm-interface to get the attestation via native Python and then send a KMS REST call with that attestation - except that isn't currently possible using botocore because it doesn't expose the Recipient key.

Unless that's possible, then it pushes those who want native code (i.e. in their programming language) to make those KMS calls by hand - i.e. not using the botocore API.

@sphw gave the example of Rusoto - and there's a clear argument with that for wanting to avoid the C API. Rust is aimed at safety - unlike C. Avoiding C completely allows a security focus - critical for those wanting to use nitro enclaves.,

@ChrisGreenaway
Copy link

The repo that contains the C API documents the REST API with Recipient directly: see "Request Syntax" in https://github.com/aws/aws-nitro-enclaves-sdk-c/blob/main/docs/kms-apis/Decrypt.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-for-staleness feature-request This issue requests a feature. response-requested Waiting on additional info and feedback. service-api This issue is caused by the service API, not the SDK implementation.
Projects
None yet
Development

No branches or pull requests

5 participants