def test_usagelimit_exceed_sym(self, auth_session, sym_key_params): """Test that changing the usage limit works as expected Gen key w/ limit = 5 Set limit = 2 Use key 2x Verify next usage returns CKR_KEY_NOT_ACTIVE """ LOG.info( "Verify that crypto operation returns error CKR_KEY_NOT_ACTIVE \ if user try to use crypto object more than limit set on CKA_USAGE_LIMIT" ) usage_lim_template = {CKA_USAGE_LIMIT: 2} key, mechanism = sym_key_params c_set_attribute_value_ex(auth_session, key, usage_lim_template) c_encrypt_ex(auth_session, key, b'a' * 2048, mechanism=mechanism) c_encrypt_ex(auth_session, key, b'a' * 2048, mechanism=mechanism) return_val, data = c_encrypt(auth_session, key, b'a' * 2048, mechanism=mechanism) py_template = c_get_attribute_value_ex( auth_session, key, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert return_val == CKR_KEY_NOT_ACTIVE, "Key should be inactive -- exceeded usage count!"
def list_kek_labels(password): ''' List labels of upto 100 keys password - string CryptoUser role password ''' # HSM slot id for HA slot_id = 5 labels = [] try: auth_session = None _initialize() auth_session = c_open_session_ex(slot_id) login_ex(auth_session, slot_id, password, CKU_CRYPTO_USER) key_handles = c_find_objects_ex(auth_session, {CKA_KEY_TYPE: CKK_AES}, 100) for handle in key_handles: label = c_get_attribute_value_ex( auth_session, handle, Attributes({CKA_LABEL: b'01234567890123456789012345'})) labels.append(label[3].decode("utf-8")) except LunaCallException: print("Exception running key mgmt operation") print(traceback.format_exc()) raise Exception('Exception running key mgmt operation') finally: if auth_session: c_logout_ex(auth_session) c_close_session_ex(auth_session) c_finalize_ex() return labels
def test_set_attribute_usage_limit_sym(self): """Test: Verify that user is able to set CKA_USAGE_LIMIT attribute on an symmetric crypto object Procedure: Generate a DES Key Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 5 Use C_getAttributeValue to verify """ LOG.info( "Test: Verify that user is able to set CKA_USAGE_LIMIT attribute on \ an symmetric crypto object") usage_template = {CKA_USAGE_LIMIT: 5} h_key = c_generate_key_ex(self.h_session, mechanism=CKM_DES_KEY_GEN, template=CKM_DES_KEY_GEN_TEMP) LOG.info("Called c-generate: Key handle -%s", h_key) usage_limit = 5 c_set_attribute_value_ex(self.h_session, h_key, usage_template) out_template = c_get_attribute_value_ex( self.h_session, h_key, template={CKA_USAGE_LIMIT: None}) usage_val_out = out_template[CKA_USAGE_LIMIT] LOG.info("CKA_USAGE_LIMIT reported by C_GetAttributeValue :%s", usage_val_out) assert usage_limit == usage_val_out, "reported USAGE LIMIT does not match"
def test_set_attribute_usage_limit_Assym(self): """Test: Verify that user is able to set CKA_USAGE_LIMIT attribute on an assymetric crypto object Procedure: Generate a RSA key pair Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 2 on RSA public key Use C_getAttributeValue to verify """ LOG.info( "Test: Verify that user is able to set CKA_USAGE_LIMIT attribute on \ an assymetric crypto object") usage_lim_template = {CKA_USAGE_LIMIT: 2} h_pbkey, h_prkey = c_generate_key_pair_ex( self.h_session, mechanism=CKM_RSA_PKCS_KEY_PAIR_GEN, pbkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PUBTEMP, prkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PRIVTEMP) LOG.info( "Called c-generate: Public Key handle: %s Private Key Handle: %s", h_pbkey, h_prkey) usage_limit = 2 c_set_attribute_value_ex(self.h_session, h_pbkey, usage_lim_template) py_template = c_get_attribute_value_ex( self.h_session, h_pbkey, template={CKA_USAGE_LIMIT: None}) usage_val_out = py_template[CKA_USAGE_LIMIT] LOG.info("CKA_USAGE_LIMIT reported by C_GetAttributeValue: %s", usage_val_out) assert usage_limit == usage_val_out, "reported USAGE LIMIT does not match"
def test_usagelimit_sym(self, auth_session, sym_key_params, usage_set): """Test: Verify that CKA_USAGE_COUNT attribute increments as user uses the symmetric crypto object Gen key w/ limit set to 5 Use key 5x Verify usage count == 5 """ _, new_limit = usage_set LOG.info( "Test: Verify that CKA_USAGE_COUNT attribute increments as user \ uses the symmetric crypto object") key, mechanism = sym_key_params for _ in range(5): c_encrypt_ex(auth_session, key, b'a' * 2048, mechanism={"mech_type": mechanism}) py_template = c_get_attribute_value_ex( auth_session, key, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert new_limit == usage_val_out, "reported USAGE LIMIT does not match"
def test_ca_get_object_handle(self): """ Testing the function CA_GetObjectHandle :return: """ h_object = c_create_object_ex(self.h_session, DATA_TEMPLATE) try: object_uid = c_get_attribute_value_ex(self.h_session, h_object, {CKA_OUID: None})[CKA_OUID] object_handle = ca_get_object_handle_ex(self.admin_slot, self.h_session, object_uid) assert h_object == object_handle finally: c_destroy_object(self.h_session, h_object)
def test_set_attribute_usage_count_check_error_CKR_KEY_NOT_ACTIVE_3des( self): """Test: Verify that crypto operation returns error CKR_KEY_NOT_ACTIVE if user try to use crypto object more than limit set on CKA_USAGE_LIMIT Procedure: Generate a 3DES key Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 2 Use RSA public key 3 times for encryption """ LOG.info( "Verify that crypto operation returns error CKR_KEY_NOT_ACTIVE \ if user try to use crypto object more than limit set on CKA_USAGE_LIMIT" ) usage_lim_template = {CKA_USAGE_LIMIT: 2} h_key = c_generate_key_ex(self.h_session, mechanism=CKM_DES3_KEY_GEN, template=CKM_DES3_KEY_GEN_TEMP) LOG.info("Called c-generate: Key handle -" + str(h_key)) c_set_attribute_value_ex(self.h_session, h_key, usage_lim_template) c_encrypt_ex(self.h_session, h_key, b'a' * 2048, mechanism={"mech_type": CKM_DES3_ECB}) c_encrypt_ex(self.h_session, h_key, b'a' * 2048, mechanism={"mech_type": CKM_DES3_ECB}) return_val, data = c_encrypt(self.h_session, h_key, b'a' * 2048, mechanism={"mech_type": CKM_DES3_ECB}) LOG.info("Called C_Encrypt, return code: %s", return_val) py_template = c_get_attribute_value_ex( self.h_session, h_key, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert return_val == CKR_KEY_NOT_ACTIVE, "reported error code does not match"
def test_usagelimit_no_use_sym(self, auth_session, sym_key_params, usage_set): """Verify that CKA_USAGE_LIMIT is reported correctly by C_GetAttribute """ LOG.info( "Test: Verify that user is able to set CKA_USAGE_LIMIT attribute on \ an symmetric crypto object") _, new_limit = usage_set key, _ = sym_key_params out_template = c_get_attribute_value_ex( auth_session, key, template={CKA_USAGE_LIMIT: None}) usage_val_out = out_template[CKA_USAGE_LIMIT] LOG.info("CKA_USAGE_LIMIT reported by C_GetAttributeValue :%s", usage_val_out) assert new_limit == usage_val_out, "reported USAGE LIMIT does not match"
def test_usage_limit_attribute_check_Assym(self): """Test: Verify that CKA_USAGE_COUNT attribute increments as user use the assymetric crypto object Procedure: Generate a RSA Key pair Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 2 Use RSA public key twice for encryption Use C_getAttributeValue to verify that CKA_USAGE_COUNT is 2 """ LOG.info( "Test: Verify that CKA_USAGE_COUNT attribute increments as user \ use the assymetric crypto object") usage_lim_template = {CKA_USAGE_LIMIT: 2} usage_count = 2 h_pbkey, h_prkey = c_generate_key_pair_ex( self.h_session, mechanism=CKM_RSA_PKCS_KEY_PAIR_GEN, pbkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PUBTEMP, prkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PRIVTEMP) LOG.info( "Called c-generate: Public Key handle -%s Private Key Handle -%s", h_pbkey, h_prkey) c_set_attribute_value_ex(self.h_session, h_pbkey, usage_lim_template) c_encrypt_ex(self.h_session, h_pbkey, b'a' * 20, mechanism={"mech_type": CKM_RSA_PKCS}) c_encrypt_ex(self.h_session, h_pbkey, b'a' * 20, mechanism={"mech_type": CKM_RSA_PKCS}) py_template = c_get_attribute_value_ex( self.h_session, h_pbkey, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert usage_count == usage_val_out, "reported USAGE LIMIT does not match"
def test_set_attribute_usage_count_check_error_CKR_KEY_NOT_ACTIVE_rsa( self): """Test: Verify that crypto operation returns error CKR_KEY_NOT_ACTIVE if user try to use crypto object more than limit set on CKA_USAGE_LIMIT Procedure: Generate a RSA Key pair Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 2 Use RSA public key 3 times for encryption """ usage_lim_template = {CKA_USAGE_LIMIT: 2} h_pbkey, h_prkey = c_generate_key_pair_ex( self.h_session, mechanism=CKM_RSA_PKCS_KEY_PAIR_GEN, pbkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PUBTEMP, prkey_template=CKM_RSA_PKCS_KEY_PAIR_GEN_PRIVTEMP) LOG.info( "Called c-generate: Public Key handle -%s Private Key Handle - %s", h_pbkey, h_prkey) c_set_attribute_value_ex(self.h_session, h_pbkey, usage_lim_template) c_encrypt_ex(self.h_session, h_pbkey, b'a' * 20, mechanism={"mech_type": CKM_RSA_PKCS}) c_encrypt_ex(self.h_session, h_pbkey, b'a' * 20, mechanism={"mech_type": CKM_RSA_PKCS}) return_val, data = c_encrypt(self.h_session, h_pbkey, b'a' * 20, mechanism={"mech_type": CKM_RSA_PKCS}) LOG.info("Called C_Encrypt, return code: %s", return_val) py_template = c_get_attribute_value_ex( self.h_session, h_pbkey, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] assert return_val == CKR_KEY_NOT_ACTIVE, "reported error code does not match"
def test_usage_limit_attribute_check_sym_des(self): """Test: Verify that CKA_USAGE_COUNT attribute increments as user use the symmetric crypto object Procedure: Generate a DES Key Use C_SetAttributeValue to set CKA_USAGE_LIMIT to 2 Use des key twice for encryption Use C_getAttributeValue to verify that CKA_USAGE_COUNT is 2 """ LOG.info( "Test: Verify that CKA_USAGE_COUNT attribute increments as user \ use the symmetric crypto object") usage_lim_template = {CKA_USAGE_LIMIT: 2} usage_count = 2 h_key = c_generate_key_ex(self.h_session, mechanism=CKM_DES_KEY_GEN, template=CKM_DES_KEY_GEN_TEMP) LOG.info("Called c-generate: Key handle -%s", h_key) c_set_attribute_value_ex(self.h_session, h_key, usage_lim_template) c_encrypt_ex(self.h_session, h_key, b'a' * 2048, mechanism={"mech_type": CKM_DES_ECB}) c_encrypt_ex(self.h_session, h_key, b'a' * 2048, mechanism={"mech_type": CKM_DES_ECB}) py_template = c_get_attribute_value_ex( self.h_session, h_key, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert usage_count == usage_val_out, "reported USAGE LIMIT does not match"
def test_asym_withusage(self, auth_session, asym_key): """ Test that USAGE_LIMIT works with asymmetric keys (private) too. """ key = asym_key with open(_get_data_file('sha1pkcs_plain.der'), 'rb') as df: data = df.read() for _ in range(5): c_sign_ex(auth_session, key, data, CKM_RSA_PKCS) return_val, data = c_sign(auth_session, key, data, CKM_RSA_PKCS) py_template = c_get_attribute_value_ex( auth_session, key, template={CKA_USAGE_COUNT: None}) usage_val_out = py_template[CKA_USAGE_COUNT] LOG.info("CKA_USAGE_COUNT reported by C_GetAttributeValue: %s", usage_val_out) assert return_val == CKR_KEY_NOT_ACTIVE, "Key should be inactive -- exceeded usage count!"
def test_data_create(self): """Tests C_CreateObject with a data template and verifies the object's attributes """ template = get_session_template(DATA_TEMPLATE) h_object = c_create_object_ex(self.h_session, template) try: desired_attrs = {x: None for x in template.keys()} attr = c_get_attribute_value_ex(self.h_session, h_object, template=desired_attrs) # CKA_VALUE in the template is a list of ints, but is returned as a single hex string. # Let's try to convert it back to the list of ints. value = attr[CKA_VALUE] attr[CKA_VALUE] = [ int(value[x:x + 2], 16) for x in range(0, len(value), 2) ] assert attr == template finally: c_destroy_object(self.h_session, h_object)
def test_x9_key_derive(self, auth_session, curve_type): """ Test we can do X9 key derivation """ derived_key2 = derived_key1 = pub_key1 = pub_key2 = prv_key2 = prv_key1 = None derived_template = { CKA_CLASS: CKO_SECRET_KEY, CKA_KEY_TYPE: CKK_DES, CKA_ENCRYPT: True, CKA_DECRYPT: True, CKA_PRIVATE: True, CKA_SENSITIVE: True } pub_temp, priv_temp = get_default_key_pair_template( CKM_ECDSA_KEY_PAIR_GEN) priv_temp = get_session_template(priv_temp) pub_temp = get_session_template(pub_temp) pub_temp[CKA_ECDSA_PARAMS] = curve_list[curve_type] pub_key1, prv_key1 = c_generate_key_pair_ex(auth_session, CKM_ECDSA_KEY_PAIR_GEN, pbkey_template=pub_temp, prkey_template=priv_temp) try: pub_key2, prv_key2 = c_generate_key_pair_ex( auth_session, CKM_ECDSA_KEY_PAIR_GEN, pbkey_template=pub_temp, prkey_template=priv_temp) pub_key1_raw = c_get_attribute_value_ex( auth_session, pub_key1, {CKA_EC_POINT: None})[CKA_EC_POINT] pub_key2_raw = c_get_attribute_value_ex( auth_session, pub_key2, {CKA_EC_POINT: None})[CKA_EC_POINT] derived_key1 = c_derive_key_ex(auth_session, h_base_key=prv_key2, template=derived_template, mechanism={ "mech_type": CKM_ECDH1_DERIVE, "params": { "kdf": CKD_NULL, "sharedData": None, "publicData": pub_key1_raw } }) derived_key2 = c_derive_key_ex(auth_session, h_base_key=prv_key1, template=derived_template, mechanism={ "mech_type": CKM_ECDH1_DERIVE, "params": { "kdf": CKD_NULL, "sharedData": None, "publicData": pub_key2_raw } }) cipher_data = c_encrypt_ex(auth_session, derived_key1, data=DATA, mechanism=CKM_DES_ECB) restored_text = c_decrypt_ex(auth_session, derived_key2, cipher_data, mechanism=CKM_DES_ECB) assert DATA == restored_text.rstrip(b'\x00') finally: for key in (pub_key1, prv_key1, pub_key2, prv_key2, derived_key1, derived_key2): if key: c_destroy_object(auth_session, key)
# The label/search string to find key: search_template = { CKA_LABEL: b"ECDSA Bitcoin Public Key" # E.g. the newly created key } # Find the key with the search: keys = c_find_objects_ex(auth_session, search_template, 1) prv_key = keys.pop(0) # Use the first (and only) key found. # For retrieving attributes we just set the value to of the attribute to None. # Pycryptoki will then figure out the length for that attribute used as a # buffer that is overwritten with the found value: attribute_template = { CKA_EC_POINT: None } result_pub = c_get_attribute_value_ex(auth_session, prv_key, attribute_template) # The stored attribute is an uncompressed public key using "DER-encoding of # ANSI X9.62 ECPoint value Q"with the last to bytes representing, see: # https://www.cryptsoft.com/pkcs11doc/v220/group__SEC__12__3__3__ECDSA__PUBLIC__KEY__OBJECTS.html # However, the first two bytes represent something (e.g. the curve used, etc.) # which I don't know what is an must be trimmed to get the uncompressed # public key used with Bitcoin. pub_key = result_pub[CKA_EC_POINT][4:] # We trim the first two bytes print('Uncompressed public key:') print(pub_key) # TODO: Convert the uncompressed public key to compressed public key # TODO: Convert the public key to address address = b'1BTC'