AWS Enclave & KMS

Project Structure

  • bin
    • kmstool-enclave — example project that runs inside enclave and calls kms:decrypt
    • kmstool-enclave-cli — same functionality as kmstool-enclave but of more ‘cli’ flavor
    • kmstool-instance — example project that calls kmstool-enclave via vsock and decrypt a message
  • containers
    • Dockerfile.al2
  • include — common headers for general aws functionality, attestation and KMS
  • source — implementations
  • tests — tests

kmstool-enclave

Overall, kmstool-enclave:

  1. runs inside an enclave container
  2. listens from vsock to receive calls from host machine (in our case, kmstool-instance will be the sender)
  3. calls aws kms:decrypt to decrypt the message received from host

Code

Setup KMS Client

// kmstool-enclave main.c
struct aws_credentials *new_credentials = s_read_credentials(app_ctx->allocator, object);
configuration.credentials = new_credentials;
client = aws_nitro_enclaves_kms_client_new(&configuration);

// kms.c
client->rest_client = aws_nitro_enclaves_rest_client_new(&rest_configuration);
client->keypair = aws_attestation_rsa_keypair_new(allocator, AWS_RSA_2048); // negotiate a new sym key?

Decryption

// ===== kmstool-enclave main.c ==== //
// get raw block from base64 input .Ciphertext
struct json_object *ciphertext_obj = json_object_object_get(object, "Ciphertext");
struct aws_byte_cursor ciphertext_b64 = aws_byte_cursor_from_c_str(json_object_get_string(ciphertext_obj));
rc = aws_base64_compute_decoded_len(&ciphertext_b64, &ciphertext_len);
rc = aws_byte_buf_init(&ciphertext, app_ctx->allocator, ciphertext_len);
rc = aws_base64_decode(&ciphertext_b64, &ciphertext);
rc = aws_kms_decrypt_blocking(client, &ciphertext, &ciphertext_decrypted);

// ==== kms.c (implementation of aws_kms_decrypt_blocking) ==== //

// create a new decryption request
request_structure = aws_kms_decrypt_request_new(client->allocator); 

// create attestation request with attestation_document
rc = aws_attestation_request(
    client->allocator, 
    client->keypair, 
    &request_structure->recipient->attestation_document); 
request_structure->recipient->key_encryption_algorithm = AWS_KEA_RSAES_OAEP_SHA_256;

// finalize request
request = aws_kms_decrypt_request_to_json(request_structure); 

// calling KMS service
rc = s_aws_nitro_enclaves_kms_client_call_blocking(client, kms_target_decrypt, request, &response); 
response_structure = aws_kms_decrypt_response_from_json(client->allocator, response);
rc = s_decrypt_ciphertext_for_recipient(
    client->allocator, 
    &response_structure->ciphertext_for_recipient, 
    client->keypair, 
    plaintext);

// ==== attestation.c (implementation of aws_attestation_request) ==== //
int nsm_fd = nsm_lib_init();
CBB out; CBB_init(&out, 0);
EVP_marshal_public_key(&out, keypair->key_impl);
int rc = nsm_get_attestation_doc(nsm_fd, NULL, 0, NULL, 0, CBB_data(&out), CBB_len(&out), att_doc, &att_doc_len);

// nsm_get_attestation_doc is provided by aws-nitro-enclaves-nsm-api to get the enclave's attestation document, and somehow KMS (or any AWS*) has the ability to verify it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s