Wednesday 5 September 2018

Generating an AWS CMK with external key material (YubiHSM)

AWS provides you with the ability to use your own key material (i.e. generate your own symmetric key) for use with its Key Management Service.

In this tutorial I will demonstrate the complete process from create the CMK (Customer Master Key) - to securing the a service such as EBS with it.

Note: A CMK can be generated via the AWS CLI optionally - but for this example we'll stick to the AWS console.

Firstly from the AWS Management Console go to IAM (Identity Access Management.) Proceed by clicking on 'Encryption Keys' in the lower part of the left hand navigational menu.

If this is the first time you have used the service you'll need to skip through the welcome wizard.

Proceed by selecting the appropriate region (as by default this does not correspond with the region you are currently using.)

Hit 'Create Key'. Provide an alias, key description and expand the 'Advanced Options' tab. Here you will be able to define the origin / source of the key material. By default this is generated by Amazon's KMS service - however we'll select 'External' as we wish our own HSM (YubiHSM) to do this for us.

Proceed by setting up tagging, key administrators (i.e. users or roles who can perform administrative functions like deletion of key through the AWS API) and key usage permissions (i.e. what users or services that can use the key for encryption / decryption - in this case EBS.

You'll finally be presented with a chance to download the wrapping key and import token (not that this expires after 24 hours.) Make sure the 'RSAES_OAEP_SHA_256' algorithm is selected as it's the most secure method currently and fully supported by YubiHSM. The wrapping key is used to secure the symmetric key we will be exporting from YubiHSM and the import token is simply authorises you to upload the wrapped key to IAM.

Note: A wrap key is simply a way of securing a private key - typically used when a key is mobile e.g. being exported to another system. If you regularly use Windows systems you will have likely come across PKCS12 which is used to wrap keys.

The next step is to import our wrap key into YubiHSM - this can be performed 1 of 2 ways - either import it directly from the terminal:

./yubihsm-shell -a put-asymmetric -A aes256-ccm-wrap -c export_wrapped,import_wrapped --delegated=asymmetric_sign_pkcs,asymmetric_decrypt_pkcs,export_under_wrap --in=wrappingKey_wxyz -i 0x150

We can confirm it's been imported with:

session open 1
created session 0
list objects 0

We'll generate our symmetric key with:

get random <session-id> <pseudo-bytes> <out-file>

Note: As per the documentation for every 'pseudo byte' you get two bytes of data - so if in the event we are generating a 256 bit key we need to generate 32 bytes (258 / 8.) So in this case we need to generate 16 pseudo bytes:

get random 0 16 key.bin   

The ls output confirms the file is equal to 32 bytes:

ls -l key.bin

-rw-rw-r-- 1 user user 32 Sep  5 12:12 key.bin

or if you are in a test environment (and the following command should only even be run in one - due to lack of true randomness) you can perform it on a Linux box with:

openssl rand -rand /dev/urandom <bytes>


openssl rand -rand /dev/urandom 32> key.bin

Since urandom takes bytes and we need 256 bits we do 256 / 8 = 32 bytes.

and to wrap the key:

openssl pkeyutl -in key.bin -out key.bin.enc -inkey wrappingKey_wxyz -keyform DER -pubin -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256

Return to the IAM key wizard page and click on the 'I am ready to upload my exported key material' and hit Next. Specify the Key Material (key.bin.enc), the import token (importToken_1234567...) and whether the key expires or not. Finally hit 'Finish.'

Note: You can also perform this operation from the AWS CLI with:

aws kms –region eu-west-1 import-key-material --key-id key-alias123456789 --encrypted-key-material fileb://key.bin.enc --import-token fileb://importToken_1234567... --expiration-model KEY_MATERIAL_DOES_NOT_EXPIRE

We can now create a newly created encrypted EBS volume. From the AWS Management Console go to EC2 >> Elastic Block Store >> Volumes >> 'Create Volume' and ensure that the 'Encrypt this Volume' is ticked. Select the newly created CMK and hit 'Create Volume.'

The last step is to ensure we import our unencrypted key material (key.bin) is imported into our YubiHSM - this can be done with the 'put opaque' command:

put opaque 0 0 aws-cmk 1 export_wrapped,import_wrapped opaque key.bin

Note: This key should also be included as part of your backup policy in the event that the YubiHSM device is lost / stolen or damaged.



Post a Comment