How do I share keys with other users to only allow certain crypto functions in CloudHSM?
I want to allow a user to wrap a key, and allow another user to unwrap only that same key.
Short description
You can share user access to keys stored in HSMs in your AWS CloudHSM cluster. When you share a key with a crypto user, that user can then use the key in cryptographic functions. That user can't delete, export, share, or unshare the key. Also, that user can't change key attributes.
To share a key with a crypto user but limit that user to specific cryptographic functions, export the key and then re-import it, twice. The imported key attributes change with permissions to wrap or unwrap. Then, the key is shared with different users to perform the wrap or unwrap functions.
Resolution
List all users in your cluster
To list all users in your cluster, use the CloudHSM Command Line Interface (CLI). Make sure that you're using interactive command mode:
$ /opt/cloudhsm/bin/cloudhsm-cli interactive
Log in with your crypto user. The following example command shows logging in as a crypto user called crypto_user1:
aws-cloudhsm > login --username crypto_user1 --role crypto-user
To list all users in the CloudHSM cluster, run the following command:
aws-cloudhsm > user list Output: { "error_code": 0, "data": { "users": [{ "username": "crypto_user1", "role": "crypto-user", "locked": "false", "mfa": [], "quorum": [], "cluster-coverage": "full" }, { "username": "crypto_user2", "role": "crypto-user", "locked": "false", "mfa": [], "quorum": [], "cluster-coverage": "full" } ] } }
Create an AES symmetric key
Use the CloudHSM CLI to create a symmetric key to encrypt and decrypt. To create an AES 256 bit key with the label rootKey, run the following command. Include attributes to wrap and unwrap in the command:
aws-cloudhsm > key generate-symmetric aes --label rootKey --key-length-bytes 32 --attributes wrap=true unwrap=true Output: { "error_code": 0, "data": { "key": { "key-reference": "0x00000000000000123", "key-info": { "key-owners": [ { "username": "crypto_user1", "key-coverage": "full" } ], "shared-users": [], "cluster-coverage": "full" }, "attributes": { "key-type": "aes", "label": "rootKey", "id": "0x", "check-value": "0xabcdefg", "class": "secret-key", "encrypt": false, "decrypt": false, "token": true, "always-sensitive": true, "derive": false, "destroyable": true, "extractable": true, "local": true, "modifiable": true, "never-extractable": false, "private": true, "sensitive": true, "sign": true, "trusted": false, "unwrap": true, "verify": true, "wrap": true, "wrap-with-trusted": false, "key-length-bytes": 32 } } } }
The output is the key that can be wrapped, unwrapped, and then shared.
Create a session key
To create an AES 256 bit session key with the label sessionKey, run the following command. You must specify --session. Set the wrap attribute to true with --attributes wrap=true:
aws-cloudhsm > key generate-symmetric aes --label sessionKey --key-length-bytes 32 --session --attributes wrap=true unwrap=true
Note: The session key is deleted after the session closes.
Write the key to disk and keep the key secret
Use the key wrap command to wrap the symmetric key rootKey to a file on your local drive. The rootKey is encrypted with the session key sessionKey. This encryption makes sure that you don't store the symmetric key rootKey in plaintext outside your HSM. After you wrap the rootKey to your local drive, use the key unwrap command to import the rootKey back to the HSM. Create a copy of the rootKey inside the HSM. Then, change the attributes of the rootKey copy to restrict how the key is used.
In the following example, the sessionKey wraps the rootKey, and then saves it to the local drive as the root.key file:
aws-cloudhsm > key wrap aes-gcm --payload-filter attr.label=rootKey --wrapping-filter attr.label=sessionKey --tag-length-bits 64 --aad 0x10 --path root.key Output: { "error_code": 0, "data": { "payload-key-reference": "0x0000000000120000", "wrapping-key-reference": "0x0000000000220000", "iv": "0xabcdefghijklmno123456789", "wrapped-key-data": "abcdefghi123456789123456789123456789123456789123456789==" } }
Important: Note the iv value that's returned from the output. You will use this value later.
To view the wrapped key in your local directory, use the ls command.
Import the keys back to your HSM with new labels
To import the key root.key back into the HSM, use the key unwrap command. The sessionKey decrypts the encrypted root.key file back to the HSM. The following example defines new keys: shared_rootKey1 and shared_rootKey2. You must define iv from the key wrap command output:
aws-cloudhsm > key unwrap aes-gcm --key-type-class aes --label shared_rootKey1 --filter attr.label=sessionKey --tag-length-bits 64 --aad 0x10 --iv 0xabcdefghijklmno123456789 --data-path root.key --attributes wrap=true
Note: Make sure that the shared_rootKey1 has the attribute wrap=true.
aws-cloudhsm > key unwrap aes-gcm --key-type-class aes --label shared_rootKey2 --filter attr.label=sessionKey --tag-length-bits 64 --aad 0x10 --iv 0xabcdefghijklmno123456789 --data-path root.key --attributes unwrap=true
Note: Make sure that the shared_rootKey2 has the attribute unwrap=true.
Verify key labels and assign attributes
To check all the key labels owned by crypto_user1, run the following command. For each key label, specify the following filters:
- shared_rootKey1 has the attribute wrap=true, unwrap=false.
- shared_rootKey2 has the attribute wrap=false, unwrap=true.
aws-cloudhsm > key list --verbose --filter attr.label=shared_rootKey1 aws-cloudhsm > key list --verbose --filter attr.label=shared_rootKey2
Confirm that all attributes are set correctly
To confirm that share_rootKey1 can wrap a key and that share_rootKey2 can only unwrap a key, use both keys as wrapping keys toward the same key material.
To use share_rootKey2 to wrap the rootKey, run the following command:
aws-cloudhsm > key wrap aes-gcm --payload-filter attr.label=rootKey --wrapping-filter attr.label=shared_rootKey2 --tag-length-bits 64 --aad 0x10 --path test_root.key Output: { "error_code": 1, "data": "Key can not be used for wrapping." }
This command fails because share_rootKey2 has the wrap attribute false.
To use share_rootKey1 to wrap the rootKey, run the following command:
aws-cloudhsm > key wrap aes-gcm --payload-filter attr.label=rootKey --wrapping-filter attr.label=shared_rootKey1 --tag-length-bits 64 --aad 0x10 --path test_root.key Output: { "error_code": 0, "data": { "payload-key-reference": "0x0000000000220000", "wrapping-key-reference": "0x0000000000330000", "iv": "0x123456abcdefghijklmno123", "wrapped-key-data": "123456abcdefghi123456789123456789123456789123456789123==" } }
This command succeeds because share_rootKey1 has the wrap attribute true.
Share keys with a crypto user
Use the key share command to share keys with crypto_user2. The user crypto_user2 can use the key for allowed cryptographic functions but that user can't delete, export, share, unshare, or change the key attributes. To share a key, run the following command:
aws-cloudhsm > key share --filter attr.label="shared_rootKey1" attr.class=secret-key --username crypto_user2 --role crypto-user Output: { "error_code": 0, "data": { "message": "Key shared successfully" } } aws-cloudhsm > key share --filter attr.label="shared_rootKey2" attr.class=secret-key --username crypto_user2 --role crypto-user Output: { "error_code": 0, "data": { "message": "Key shared successfully" } }
Test functionality of the wrapKey command between the disk and your HSM
Log in as crypto_user2 to verify functionality of the keys with the CloudHSM CLI. Test that crypto_user2 can use shared_rootKey1 to wrap, and that the user can use shared_rootKey2 to unwrap.
To generate a testing key, run the following command:
aws-cloudhsm > key generate-symmetric aes --label testKey --key-length-bytes 32 --session
Use shared_rootKey1 to wrap the testKey and save as file test.key, as the following example shows:
aws-cloudhsm > key wrap aes-gcm --payload-filter attr.label=testKey --wrapping-filter attr.label=shared_rootKey1 --tag-length-bits 64 --aad 0x10 --path test.key Output: { "error_code": 0, "data": { "payload-key-reference": "0x0000000000aa0000", "wrapping-key-reference": "0x0000000000bb0000", "iv": "0x00abcd123abcdefghijklmno", "wrapped-key-data": "xyz123abcdefghi123456789123456789123456789123456789123==" } }
Important: Note the iv value that's returned from the output. You will use this value later.
Use shared_rootKey2 to unwrap the testKey, as shown in the following command:
aws-cloudhsm >key unwrap aes-gcm --key-type-class aes --label imported_testKey --filter attr.label=shared_rootKey2 --tag-length-bits 64 --aad 0x10 --iv 0x00abcd123abcdefghijklmno --data-path test.key
To verify that crypto_user2 can't change the attributes of the key, run the following command:
aws-cloudhsm > key set-attribute --filter attr.label=shared_rootKey1 --name unwrap --value true { "error_code": 1, "data": "The current user does not have adequate key permissions to perform the key operation" }
Related information

Relevant content
- asked 3 years agolg...
- Accepted Answerasked a year agolg...
- Accepted Answerasked 2 years agolg...
- asked 5 months agolg...
- asked 9 days agolg...
- AWS OFFICIALUpdated 8 months ago
- AWS OFFICIALUpdated 4 months ago
- AWS OFFICIALUpdated 8 months ago
- AWS OFFICIALUpdated a year ago