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:
- runs inside an enclave container
- listens from vsock to receive calls from host machine (in our case, kmstool-instance will be the sender)
- 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.
Pages: 1 2
