python-pkcs11
python-pkcs11 copied to clipboard
CloudHSM Support
Hi! I'm wondering if there is a project to add CloudHSM on the list of supported devices. I can help with the implementation.
Please tag this as feature request!
Yes, I'd be very interested in adding CloudHSM to the support list. I don't have access to a CloudHSM setup, would it be possible to add a Buildbot client to an EC2 connected to CloudHSM? Then we could test pull requests against the device immediately.
I can confirm that python-pkcs11 works with CloudHSM, as I'm running a workload in exactly that configuration. Of course this isn't the same as it being supported. :-) As far as ongoing testing is concerned, I guess the main factor would be cost: CloudHSM costs ~ $1.50 an hour to run.
Of course you could spin the CloudHSM down when it's not being used and there's nothing to test but then the test has a fair bit more work to do (spin up CloudHSM, connect etc, run tests, spin down). A possibility though.
I think there's also a significant upfront payment to provision a CloudHSM into your environment. Basically I don't have that kind of money. I'd hoped to convince Amazon to donate some resources, but I haven't succeeded yet.
There used to be an upfront cost, under the original CloudHSM product (now rebadged 'CloudHSM Classic'). Basically you'd purchase a device and they'd rack it for you and look after it. Not very cloudy at all.
However in August they massively updated the product and it's now much more of a cloud-native product; no up-front cost, per-hour billing, spin up/down at will, etc. It's different hardware (was Safenet Luna, now Cavium LiquidSecurity) but of course both support PKCS11.
Details: https://aws.amazon.com/blogs/aws/aws-cloudhsm-update-cost-effective-hardware-key-management/
hi, i am using the library with cloudhsm and it works just fine. i am using it for key generation and storage for both aes and rsa, and also for encryption and decryption. works really well and its simple to run. i haven't run beyond those few operations but given its pkcs#11 both ends then it should all work fine. cost wise cloudhsm is now USD $1.99 per hour per hsm (you can have just one, or a cluster). its very cheap when you consider you are getting dedicated hsm's for your exclusive use, but as a managed service.
I could set up a CloudFormation to temporarily spin up an EC2 / CloudHSM to run the unit tests, however I am sort of hoping someone might be willing to install the Buildbot on their existing test system.
I have the unit tests running with my cloudhsm but there is quite a lot of failures so I think I might be missing something since the library does work with it for the most part. The unit test logs can be found https://pastebin.com/e44v941P. The only problem I've ran into with cloudhsm only started happening recently. I am receiving a CKR_TEMPLATE_INCONSISTENT error when attempting to create an AES key. I have upgraded to 0.5.0 but unfortunately the problem persists. I had successfully created AES keys in December 2017.
I've been trying to find a user guide for the Cavium devices to get an idea of what it doesn't like, and/or any debugging environment variables that might allow it to inform us what it doesn't like.
Here is the template used to create keys:
template_ = {
Attribute.CLASS: ObjectClass.SECRET_KEY,
Attribute.ID: id or b'',
Attribute.LABEL: label or '',
Attribute.TOKEN: store,
Attribute.PRIVATE: True,
Attribute.SENSITIVE: True,
# Capabilities
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
}
if key_type is KeyType.AES:
if key_length is None:
raise ArgumentsBad("Must provide `key_length'")
template_[Attribute.VALUE_LEN] = key_length // 8 # In bytes
Without any way to increase the debug level from the device, it will have to be a process of elimination to work out which attribute is upsetting it.
i can login to the hsm and fetch all attributes for one of my keys generated using the hsm console...i'm out now but will ping through later
I have tried some elimination but I can't find anything that seems to help. I was able to extract these attributes from a key that works. I can't remember if I created this key from python last year or through the cloudhsm key management tool.
OBJ_ATTR_CLASS 0x00000004 OBJ_ATTR_DECRYPT 0x00000001 OBJ_ATTR_ENCRYPT 0x00000001 OBJ_ATTR_EXTRACTABLE 0x00000001 OBJ_ATTR_ID
OBJ_ATTR_KCV 0x8e50be OBJ_ATTR_KEY_TYPE 0x0000001f OBJ_ATTR_LABEL aes256 OBJ_ATTR_LOCAL 0x00000001 OBJ_ATTR_MODULUS_BITS 0x00000000 OBJ_ATTR_PRIVATE 0x00000001 OBJ_ATTR_SENSITIVE 0x00000001 OBJ_ATTR_SIGN 0x00000000 OBJ_ATTR_TOKEN 0x00000001 OBJ_ATTR_UNWRAP 0x00000001 OBJ_ATTR_VALUE_LEN 0x00000020 OBJ_ATTR_VERIFY 0x00000000 OBJ_ATTR_WRAP 0x00000001
The problem could be related to creating ephemeral objects in a read-only session. I had this problem on the Nitrokey too, because they just hadn’t implemented this part of the spec (or couldn’t). I didn’t change it because writes on that device are slow and I am quite fond of the release your session and all is forgotten nature of the test suite.
On 3 February 2018 at 08:21:07, Brian Richter ([email protected](mailto:[email protected])) wrote:
I have tried some elimination but I can't find anything that seems to help. I was able to extract these attributes from a key that works. I can't remember if I created this key from python last year or through the cloudhsm key management tool.
OBJ_ATTR_CLASS 0x00000004 OBJ_ATTR_DECRYPT 0x00000001 OBJ_ATTR_ENCRYPT 0x00000001 OBJ_ATTR_EXTRACTABLE 0x00000001 OBJ_ATTR_ID
OBJ_ATTR_KCV 0x8e50be OBJ_ATTR_KEY_TYPE 0x0000001f OBJ_ATTR_LABEL aes256 OBJ_ATTR_LOCAL 0x00000001 OBJ_ATTR_MODULUS_BITS 0x00000000 OBJ_ATTR_PRIVATE 0x00000001 OBJ_ATTR_SENSITIVE 0x00000001 OBJ_ATTR_SIGN 0x00000000 OBJ_ATTR_TOKEN 0x00000001 OBJ_ATTR_UNWRAP 0x00000001 OBJ_ATTR_VALUE_LEN 0x00000020 OBJ_ATTR_VERIFY 0x00000000 OBJ_ATTR_WRAP 0x00000001
— You are receiving this because you commented. Reply to this email directly, view it on GitHub(https://github.com/danni/python-pkcs11/issues/14#issuecomment-362711133), or mute the thread(https://github.com/notifications/unsubscribe-auth/AAH5wAaqyydcbKlkPsv_9uc3Dngvj9wTks5tQ3xDgaJpZM4Qbwd2).
i modified the code to use this template for AES-256 key generation and it works fine. the hsm seems to not like SENSITIVE being mentioned at all, and PRIVATE needs to be false.
template_ = { Attribute.CLASS: ObjectClass.SECRET_KEY, Attribute.VALUE_LEN: 32, Attribute.ID: id, Attribute.LABEL: label, Attribute.TOKEN: True, Attribute.PRIVATE: False, Attribute.EXTRACTABLE: True, Attribute.LOCAL: True, Attribute.ENCRYPT: True, Attribute.DECRYPT: True, Attribute.SIGN: False, Attribute.VERIFY: False, Attribute.WRAP: True, Attribute.UNWRAP: True }
PRIVATE = False
suggests that the object can be read without being authenticated. However it may be unhappy with the values being provided at all.
Hello there, folks! I've been working with CloudHSM and PyKCS11, but last week I started testing it with python-pkcs11. BTW, danni, your documentation is really good!
Let me highlight some important points so as to help you, folks:
- For all key types, CKA_PRIVATE must be set to TRUE. Otherwise, you can have trouble with the latest versions of the CloudHSM [1]. This is an example of how to generate AES keys:
internal_key = session.generate_key(KeyType.AES, 256, label="AES_internal_key", mechanism=Mechanism.AES_KEY_GEN, template={ Attribute.CLASS: ObjectClass.SECRET_KEY, Attribute.TOKEN: True, Attribute.PRIVATE: True, Attribute.SENSITIVE: True, Attribute.ENCRYPT: True, Attribute.DECRYPT: True, Attribute.WRAP: True, Attribute.UNWRAP: True, Attribute.SIGN: False, Attribute.VERIFY: False, Attribute.EXTRACTABLE: True, Attribute.VALUE_LEN: 32, Attribute.DERIVE: True })
These are the version of the CloudHSM packages I have installed on my client instance (Amazon Linux 1):
cloudhsm-client-1.1.1-1.el6.x86_64 cloudhsm-client-pkcs11-1.1.1-1.el6.x86_64
- If you want to increase the log level of the CloudHSM client process, edit the /opt/cloudhsm/etc/cloudhsm_client.cfg file, changing the log_level parameter from INFO to DEBUG. Then, reload the CloudHSM client process by running:
sudo stop cloudhsm-client sudo start cloudhsm-client
The logs are written to /opt/cloudhsm/run/cloudhsm_client.log.
danni, could you please send me the instructions of how to set up Buildbot so as to perform the python-pkcs11 tests?
[1] https://docs.aws.amazon.com/cloudhsm/latest/userguide/client-history.html
Thanks! So much PKCS#11 documentation is unhelpful and vague. After reading so many different documents, and so much source code, to learn how to program PKCS#11, I figured people deserved some clear documentation.
Unfortunately following a data centre move, I think the machine that had my HSM devices plugged into it is offline, and so the buildbot is offline.
The tests themselves are straightforward to run, just built on the Python unittest
module, e.g.
# export PKCS11_MODULE=
# export PKCS11_TOKEN_LABEL=
# export PKCS11_TOKEN_PIN=
python -m unittest
Hey, danni, thanks for info! Let me ask you something...
I've created a Python code that performs wrapping/unwrapping of AES keys. It's working fine.
Now I'm writing a script to perform wrapping/unwrapping of RSA private keys. The wrapping operation is fine, however I'm getting the following error when trying to unwrap the wrapped key:
C_UnwrapKey failed with error CKR_TEMPLATE_INCONSISTENT : 0x000000d1
key_template = { Attribute.PRIVATE: True, Attribute.SENSITIVE: True, Attribute.DECRYPT: True, Attribute.SIGN: True, Attribute.UNWRAP: True, Attribute.LABEL: "unwrapped_rsa_private_key", Attribute.EXTRACTABLE: True Attribute.DERIVE: False }
I noticed that, when you don't specify the parameter 'capabilities' for unwrap_key(), it uses a default value as follows:
capabilities = DEFAULT_KEY_CAPABILITIES[key_type]
This results in the following value:
MechanismFlag.ENCRYPT | MechanismFlag.DECRYPT | MechanismFlag.SIGN | MechanismFlag.VERIFY | MechanismFlag.WRAP | MechanismFlag.UNWRAP
Since I'm unwrapping a private key, I specified a custom capabilities set as follows:
key_capabilities = MechanismFlag.DECRYPT | MechanismFlag.SIGN | MechanismFlag.UNWRAP
And then I invoked unwrap_key() as follows:
unwrapped_key = wrapping_key.unwrap_key(ObjectClass.PRIVATE_KEY, KeyType.RSA, wrapped_key, mechanism=Mechanism.AES_KEY_WRAP, store=True, capabilities=key_capabilities, template=key_template)
But I'm still getting the error CKR_TEMPLATE_INCONSISTENT.
Is there any way to see the complete template that is being sent to C_UnwrapKey?
Nothing currently logs the templates, one could add that easily enough.
Here's the prototype template (_pkcs11.pyx:1051
):
template_ = {
Attribute.CLASS: object_class,
Attribute.KEY_TYPE: key_type,
Attribute.ID: id or b'',
Attribute.LABEL: label or '',
Attribute.TOKEN: store,
# Capabilities
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
}
Your attributes would then be update()
ed onto these.
I am trying to generate an EC-keypair using python-pkcs11 with CloudHSMv2 using LunaHSM. But I am also getting the same known error message: C_GenerateKeyPair failed with error CKR_TEMPLATE_INCOMPLETE : 0x000000d0
.
For AES keys, providing a template as @suzue-chan showed in his post above (https://github.com/danni/python-pkcs11/issues/14#issuecomment-422433078) did allow me to create an AES key.
Does anyone know public and private templates that can be provided for CloudHSM to generate an EC keypair with python-pkcs11?
Now I'm writing a script to perform wrapping/unwrapping of RSA private keys. The wrapping operation is fine, however I'm getting the following error when trying to unwrap the wrapped key:
C_UnwrapKey failed with error CKR_TEMPLATE_INCONSISTENT : 0x000000d1
Not that it helps much, but I'm also hitting that issue using https://github.com/bentonstark/py-hsm. I suspect this might be a firmware and/or client software issue (not exactly unlikely given https://docs.aws.amazon.com/cloudhsm/latest/userguide/KnownIssues.html).
Oh, hang on, I've just realised that I'm hitting that with AES keys, but you said you got that working? If so, what template did you use for the unwrapped key?
It's probably also important to note here that the Cavium devices that CloudHSMv2 use don't support wrapping keys using an RSA key. You can wrap RSA keys with an AES key, but not the other way around, as CKM_AES_KEY_WRAP is the only supported key wrap mechanism (https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-mechanisms.html).
Is there any way to see the complete template that is being sent to C_UnwrapKey?
Based on: https://www.cryptsoft.com/pkcs11doc/v220/pkcs11__all_8h.html#aC_UnwrapKey
To partition the unwrapping keys so they can only unwrap a subset of keys the attribute CKA_UNWRAP_TEMPLATE can be used on the unwrapping key to specify an attribute set that will be added to attributes of the key to be unwrapped. If the attributes do not conflict with the user supplied attribute template, in 'pTemplate', then the unwrap will proceed. The value of this attribute is an attribute template and the size is the number of items in the template times the size of CK_ATTRIBUTE. If this attribute is not present on the unwrapping key then no additional attributes will be added. If any attribute conflict occurs on an attempt to unwrap a key then the function shall return CKR_TEMPLATE_INCONSISTENT.
Is it possible that you have an unwrap template on the wrapping key that collides with the passed in pTemplate? The pTemplate should be blank, shouldn't it? If the Unwrap Template is present then all values should apply to the unwrapped key and not have any collisions.
... sorry to bump an old discussion, I was unsure if the comments here have been resolved.
It's probably also important to note here that the Cavium devices that CloudHSMv2 use don't support wrapping keys using an RSA key. You can wrap RSA keys with an AES key, but not the other way around, as CKM_AES_KEY_WRAP is the only supported key wrap mechanism (https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-mechanisms.html).
RSA Wraps/Unwraps with Encrypt/Decrypt. Mechanism=CKM_RSA_PKCS
I believe the unwrapping issues are now being sorted out in #44 / #45. Does anyone feel like putting together a page for the documentation on any template changes required to use CloudHSM ?
Let me document something here while I still have access to Gemalto SafeNet (== standalone version of CloudHSM v1). With commit https://github.com/danni/python-pkcs11/commit/bc372de1485c7cd4cb37aeda2a30cbcd493b53e1:
unwrap_key
now works (AES-CBC-PAD
, DES3-CBC-PAD
of a private key onto the HSM) but the template needs to have a few flags deleted:
# these capabilities must not be sent to the HSM or you will get
# inconsistent template error...
# DEFAULT is new in the commit and represents "delete this attribute from the
# outgoing template"
template={ pkcs11.Attribute.ENCRYPT: pkcs11.constants.DEFAULT,
pkcs11.Attribute.VERIFY: pkcs11.constants.DEFAULT,
pkcs11.Attribute.WRAP: pkcs11.constants.DEFAULT }
The other flags DECRYPT SIGN UNWRAP DERIVE are all fine.
CloudHSM doesn't seem to support C_SetAttributeValue.
The only attribute supported for C_SetAttributeValue is Attribute.TOKEN
(OBJ_ATTR_TOKEN).
(only the following attribute's value can be modified)
OBJ_ATTR_TOKEN = 1
CloudHSM also doesn't support C_GetAttributeValue for most of the attributes.
C_GetAttributeValue failed with error CKR_ATTRIBUTE_TYPE_INVALID : 0x00000012
The following are all of the possible attribute values for getAttributes.
OBJ_ATTR_CLASS = 0
OBJ_ATTR_TOKEN = 1
OBJ_ATTR_PRIVATE = 2
OBJ_ATTR_LABEL = 3
OBJ_ATTR_KEY_TYPE = 256
OBJ_ATTR_ID = 258
OBJ_ATTR_SENSITIVE = 259
OBJ_ATTR_ENCRYPT = 260
OBJ_ATTR_DECRYPT = 261
OBJ_ATTR_WRAP = 262
OBJ_ATTR_UNWRAP = 263
OBJ_ATTR_SIGN = 264
OBJ_ATTR_VERIFY = 266
OBJ_ATTR_LOCAL = 355
OBJ_ATTR_MODULUS = 288
OBJ_ATTR_MODULUS_BITS = 289
OBJ_ATTR_PUBLIC_EXPONENT = 290
OBJ_ATTR_VALUE_LEN = 353
OBJ_ATTR_EXTRACTABLE = 354
OBJ_ATTR_KCV = 371