How do I share keys with other users to only allow certain crypto functions in CloudHSM?

7 minute read
0

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

Reference for CloudHSM CLI commands

Activate the cluster

AWS OFFICIAL
AWS OFFICIALUpdated 6 months ago