CK_RV counter_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { OCK_LOG_ERR(ERR_TEMPLATE_INCOMPLETE); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_HAS_RESET, &attr ); if (!found) { OCK_LOG_ERR(ERR_TEMPLATE_INCOMPLETE); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_RESET_ON_INIT, &attr ); if (!found) { OCK_LOG_ERR(ERR_TEMPLATE_INCOMPLETE); return CKR_TEMPLATE_INCOMPLETE; } } return hwf_object_check_required_attributes( tmpl, mode ); }
CK_RV sign_mgr_init( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; if (!sess || !ctx){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ OCK_LOG_ERR(ERR_OPERATION_ACTIVE); return CKR_OPERATION_ACTIVE; } // key usage restrictions // rc = object_mgr_find_in_map1( key, &key_obj ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_KEY_HANDLE_INVALID); return CKR_KEY_HANDLE_INVALID; } // is key allowed to generate signatures? // rc = template_attribute_find( key_obj->template, CKA_SIGN, &attr );
CK_RV md2_hash( SESSION * sess, CK_BBOOL length_only, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD2_HASH_SIZE; return CKR_OK; } rc = md2_hash_update( sess, ctx, in_data, in_data_len ); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } return md2_hash_final( sess, FALSE, ctx, out_data, out_data_len ); }
CK_RV des3_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE key_value[3*DES_KEY_SIZE]; CK_KEY_TYPE keytype; CK_RV rc; if (!sess || !ctx || !out_data_len){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } // CKM_DES3_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ OCK_LOG_ERR(ERR_DATA_LEN_RANGE); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); return rc; } rc = template_attribute_find( key->template, CKA_KEY_TYPE, &attr );
/* * Reallocate the attribute array and add the new element. */ CK_RV add_to_attribute_array(CK_ATTRIBUTE_PTR *p_attrs, CK_ULONG_PTR p_attrs_len, CK_ULONG type, CK_BYTE_PTR value, CK_ULONG value_len) { CK_ATTRIBUTE_PTR attrs; CK_BYTE_PTR copied_value; copied_value = malloc(value_len); if (copied_value == NULL) { OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } memcpy(copied_value, value, value_len); attrs = realloc(*p_attrs, sizeof(**p_attrs) * (*p_attrs_len + 1)); if (attrs == NULL) { free(copied_value); OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } attrs[*p_attrs_len].type = type; attrs[*p_attrs_len].pValue = copied_value; attrs[*p_attrs_len].ulValueLen= value_len; *p_attrs = attrs; *p_attrs_len += 1; return CKR_OK; }
CK_RV init_token_data(CK_SLOT_ID slot_id) { CK_RV rc; memset((char *)nv_token_data, 0, sizeof(nv_token_data)); // the normal USER pin is not set when the token is initialized // memcpy(nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE); memcpy(nv_token_data->so_pin_sha, default_so_pin_sha, SHA1_HASH_SIZE); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); memcpy(so_pin_md5, default_so_pin_md5, MD5_HASH_SIZE); memcpy(nv_token_data->next_token_object_name, "00000000", 8); // generate the master key used for signing the Operation State information // ` memset(nv_token_data->token_info.label, ' ', sizeof(nv_token_data->token_info.label)); memcpy(nv_token_data->token_info.label, label, strlen((char *)label)); nv_token_data->tweak_vector.allow_weak_des = TRUE; nv_token_data->tweak_vector.check_des_parity = FALSE; nv_token_data->tweak_vector.allow_key_mods = TRUE; nv_token_data->tweak_vector.netscape_mods = TRUE; init_tokenInfo(); if (token_specific.t_init_token_data) { rc = token_specific.t_init_token_data(slot_id); if (rc != CKR_OK) return rc; } else { // // FIXME: erase the token object index file (and all token objects) // rc = generate_master_key(master_key); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } rc = save_masterkey_so(); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } } rc = save_token_data(slot_id); return rc; }
// this routine gets called for two mechanisms actually: // CKM_MD2_HMAC // CKM_MD2_HMAC_GENERAL // CK_RV md2_hmac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[MD2_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[MD2_BLOCK_SIZE]; CK_BYTE k_opad[MD2_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD2_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = MD2_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr );
CK_RV dsa_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE sig[DSA_SIGNATURE_SIZE]; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); return rc; } // must be a PRIVATE key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr );
CK_RV clock_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *value_attr; rc = hwf_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!value_attr) { OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; template_update_attribute( tmpl, value_attr ); return CKR_OK; }
CK_RV md2_hash_final( SESSION * sess, CK_BYTE length_only, DIGEST_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD2_HASH_SIZE; return CKR_OK; } rc = ckm_md2_final( (MD2_CONTEXT *)ctx->context, out_data, MD2_HASH_SIZE ); if (rc == CKR_OK) { *out_data_len = MD2_HASH_SIZE; return rc; } return rc; }
CK_RV build_attribute( CK_ATTRIBUTE_TYPE type, CK_BYTE *data, CK_ULONG data_len, CK_ATTRIBUTE **attrib ) { CK_ATTRIBUTE *attr = NULL; attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + data_len ); if (!attr){ OCK_LOG_ERR(ERR_DEVICE_MEMORY); return CKR_DEVICE_MEMORY; } attr->type = type; attr->ulValueLen = data_len; if (data_len > 0) { attr->pValue = (CK_BYTE *)attr + sizeof(CK_ATTRIBUTE); memcpy( attr->pValue, data, data_len ); } else attr->pValue = NULL; *attrib = attr; return CKR_OK; }
CK_RV ckm_ec_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; rc = token_specific.t_ec_generate_keypair(publ_tmpl, priv_tmpl); if (rc != CKR_OK) OCK_LOG_ERR(ERR_KEYGEN); return rc; }
// hwf_object_validate_attribute() // CK_RV hwf_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_HW_FEATURE_TYPE: if (mode == MODE_CREATE) return CKR_OK; else{ OCK_LOG_ERR(ERR_ATTRIBUTE_READ_ONLY); return CKR_ATTRIBUTE_READ_ONLY; } default: return template_validate_base_attribute( tmpl, attr, mode ); } OCK_LOG_ERR(ERR_ATTRIBUTE_TYPE_INVALID); return CKR_ATTRIBUTE_TYPE_INVALID; }
/* * Duplicate an array of attributes and all its values. * * The returned array must be freed with free_attribute_array(). */ CK_RV dup_attribute_array(CK_ATTRIBUTE_PTR orig, CK_ULONG orig_len, CK_ATTRIBUTE_PTR *p_dest, CK_ULONG *p_dest_len) { CK_RV rc = CKR_OK; CK_ATTRIBUTE_PTR dest; CK_ULONG dest_len; CK_ATTRIBUTE_PTR it; /* Allocate the new array */ dest_len = orig_len; dest = malloc(dest_len * sizeof(*dest)); if (dest == NULL) { OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } memset(dest, 0, dest_len); /* Copy each element */ for (it = dest; it != (dest + orig_len); it++, orig++) { it->type = orig->type; it->ulValueLen = orig->ulValueLen; it->pValue = malloc(it->ulValueLen); if (it->pValue == NULL) { OCK_LOG_ERR(ERR_HOST_MEMORY); rc = CKR_HOST_MEMORY; goto done; } memcpy(it->pValue, orig->pValue, orig->ulValueLen); } done: if (rc == CKR_OK) { *p_dest = dest; *p_dest_len = dest_len; } else { free_attribute_array(dest, dest_len); } return rc; }
CK_RV md2_hash_update( SESSION * sess, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { if (!sess || !ctx || !in_data) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } return ckm_md2_update( (MD2_CONTEXT *)ctx->context, in_data, in_data_len ); }
// Function: compute_next_token_obj_name() // // Given a token object name (8 bytes in the range [0-9A-Z]) increment by one // adjusting as necessary // // This gives us a namespace of 36^8 = 2,821,109,907,456 objects before wrapping around // CK_RV compute_next_token_obj_name( CK_BYTE *current, CK_BYTE *next ) { int val[8]; int i; if (!current || !next){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } // Convert to integral base 36 // for (i = 0; i < 8; i++) { if (current[i] >= '0' && current[i] <= '9') val[i] = current[i] - '0'; if (current[i] >= 'A' && current[i] <= 'Z') val[i] = current[i] - 'A' + 10; } val[0]++; i=0; while (val[i] > 35) { val[i] = 0; if (i+1 < 8) { val[i+1]++; i++; } else { val[0]++; i = 0; // start pass 2 } } // now, convert back to [0-9A-Z] // for (i = 0; i < 8; i++) { if (val[i] < 10) next[i] = '0' + val[i]; else next[i] = 'A' + val[i] - 10; } return CKR_OK; }
CK_RV decr_mgr_init( SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (!sess){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ OCK_LOG_ERR(ERR_OPERATION_ACTIVE); return CKR_OPERATION_ACTIVE; } // key usage restrictions // if (operation == OP_DECRYPT_INIT) { rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_KEY_HANDLE_INVALID); return CKR_KEY_HANDLE_INVALID; } // is key allowed to do general decryption? // rc = template_attribute_find( key_obj->template, CKA_DECRYPT, &attr );
CK_RV rng_generate( CK_BYTE *output, CK_ULONG bytes ) { CK_RV rc; /* Do token specific rng if it exists. */ if (token_specific.t_rng != NULL) rc = token_specific.t_rng(output, bytes); else rc = local_rng(output, bytes); if (rc != CKR_OK) OCK_LOG_ERR(ERR_RNG); return rc; }
CK_RV strip_pkcs_padding(CK_BYTE * ptr, CK_ULONG total_len, CK_ULONG * data_len) { CK_BYTE pad_value; pad_value = ptr[total_len - 1]; if (pad_value > total_len) { OCK_LOG_ERR(ERR_ENCRYPTED_DATA_INVALID); return CKR_ENCRYPTED_DATA_INVALID; } // thus, we have 'pad_value' bytes of 'pad_value' appended to the end // *data_len = total_len - pad_value; return CKR_OK; }
// hwf_object_check_required_attributes() // // Check required common attributes for hardware feature objects // CK_RV hwf_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_HW_FEATURE_TYPE, &attr ); if (!found) { if (mode == MODE_CREATE){ OCK_LOG_ERR(ERR_TEMPLATE_INCOMPLETE); return CKR_TEMPLATE_INCOMPLETE; } } return template_check_required_base_attributes( tmpl, mode ); }
CK_RV counter_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: /* Fall Through */ case CKA_HAS_RESET: /* Fall Through */ case CKA_RESET_ON_INIT: OCK_LOG_ERR(ERR_ATTRIBUTE_READ_ONLY); return CKR_ATTRIBUTE_READ_ONLY; default: return hwf_validate_attribute( tmpl, attr, mode ); } }
CK_RV counter_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *value_attr; CK_ATTRIBUTE *hasreset_attr; CK_ATTRIBUTE *resetoninit_attr; rc = hwf_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); hasreset_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); resetoninit_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); if (!value_attr || !hasreset_attr || !resetoninit_attr) { if (value_attr) free( value_attr ); if (hasreset_attr) free( hasreset_attr ); if (resetoninit_attr) free( resetoninit_attr ); OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; hasreset_attr->type = CKA_HAS_RESET; hasreset_attr->ulValueLen = sizeof(CK_BBOOL); hasreset_attr->pValue = (CK_BYTE *)hasreset_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)hasreset_attr->pValue = FALSE; /* Hmm... Not sure if we should be setting this here. */ resetoninit_attr->type = CKA_RESET_ON_INIT; resetoninit_attr->ulValueLen = sizeof(CK_BBOOL); resetoninit_attr->pValue = (CK_BYTE *)resetoninit_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)resetoninit_attr->pValue = FALSE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, hasreset_attr ); template_update_attribute( tmpl, resetoninit_attr ); return CKR_OK; }
CK_RV add_pkcs_padding(CK_BYTE * ptr, CK_ULONG block_size, CK_ULONG data_len, CK_ULONG total_len) { CK_ULONG i, pad_len; CK_BYTE pad_value; pad_len = block_size - (data_len % block_size); pad_value = (CK_BYTE) pad_len; if (data_len + pad_len > total_len) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } for (i = 0; i < pad_len; i++) ptr[i] = pad_value; return CKR_OK; }
// hwf_object_set_default_attributes() // CK_RV hwf_object_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { #if 0 CK_ATTRIBUTE * local_attr = NULL; local_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!local_attr) { OCK_LOG_ERR(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = FALSE; template_update_attribute( tmpl, local_attr ); #endif return CKR_OK; }
static AEP_RV GetAEPConnection(AEP_CONNECTION_HNDL *hConnection) { int count; AEP_RV rv = AEP_R_OK; pid_t curr_pid = getpid(); pthread_mutex_lock(&AEP_ThreadPool_mutex); // Check if this is the first time this is being called // from the current process // if (recorded_pid != curr_pid) { if (aep_initialised != TRUE) { aep_initialised = TRUE; recorded_pid = curr_pid; AEP_Finalize(); /*Initialise the AEP API*/ if ( (rv = AEP_Initialize(NULL)) != AEP_R_OK) { aep_initialised = FALSE; recorded_pid = 0; goto end; } /*Set the AEP big num call back functions*/ rv = AEP_SetBNCallBacks(&GetBigNumSize, &MakeAEPBigNum, &ConvertAEPBigNum); if (rv != AEP_R_OK) { aep_initialised = FALSE; recorded_pid = 0; goto end; } /*Init the structures*/ for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) { aep_app_conn_table[count].conn_state = NotConnected; aep_app_conn_table[count].conn_hndl = 0; } if ( (rv = AEP_OpenConnection(hConnection)) != AEP_R_OK) { /* a problem here, assume AEP subsystem is dead ! */ cryptoki_aep_avail = FALSE; aep_initialised = FALSE; recorded_pid = 0; OCK_LOG_ERR(ERR_DEVICE_ERROR); goto end; } aep_app_conn_table[0].conn_state = InUse; aep_app_conn_table[0].conn_hndl = *hConnection; goto end; } for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) { if (aep_app_conn_table[count].conn_state == Connected) { aep_app_conn_table[count].conn_state = InUse; *hConnection = aep_app_conn_table[count].conn_hndl; goto end; } } /*If no connections available, we try to open a new one*/ for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) { if (aep_app_conn_table[count].conn_state == NotConnected) { rv = AEP_OpenConnection(hConnection); if ( rv != AEP_R_OK){ // a problem here, assume AEP subsystem is dead ! cryptoki_aep_avail = FALSE; OCK_LOG_ERR(ERR_DEVICE_ERROR); goto end; } aep_app_conn_table[count].conn_state = InUse; aep_app_conn_table[count].conn_hndl = *hConnection; goto end; } } rv = AEP_R_GENERAL_ERROR; end: pthread_mutex_unlock(&AEP_ThreadPool_mutex); return rv; }
CK_RV dh_pkcs_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { CK_RV rc; CK_ULONG i, keyclass, keytype = 0 ; CK_ATTRIBUTE *new_attr ; OBJECT *temp_obj = NULL; OBJECT *secret_obj = NULL ; CK_BYTE secret_key_value[256] ; CK_ULONG count, secret_key_value_len = 256 ; CK_ATTRIBUTE *attr ; // Prelim checking of sess, mech, pTemplate, and ulCount was // done in the calling function (key_mgr_derive_key). // Perform DH checking of parameters // Check the existance of the public-value in mechanism if ((!mech->pParameter) || ((mech->ulParameterLen != 64) && (mech->ulParameterLen != 96) && (mech->ulParameterLen != 128) && (mech->ulParameterLen != 192) && (mech->ulParameterLen != 256))) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } // Check valid object handle on base_key if (&base_key == NULL) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } // Extract the object class and keytype from the supplied template. for (i=0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; if (keyclass != CKO_SECRET_KEY) { OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } } if (pTemplate[i].type == CKA_KEY_TYPE) keytype = *(CK_ULONG *)pTemplate[i].pValue; } // Extract public-key from mechanism parameters. base-key contains the // private key, prime, and base. The return value will be in the handle. rc = ckm_dh_pkcs_derive( mech->pParameter, mech->ulParameterLen, base_key, secret_key_value, &secret_key_value_len ); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED ; } // Build the attribute from the vales that were returned back rc = build_attribute( CKA_VALUE, secret_key_value, secret_key_value_len, &new_attr ); if (rc != CKR_OK) { OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED ; } // Create the object that will be passed back as a handle. This will // contain the new (computed) value of the attribute. rc = object_mgr_create_skel( sess, pTemplate, ulCount, MODE_KEYGEN, keyclass, keytype, &temp_obj ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_OBJMGR_CREATE_SKEL); return rc; } // Update the template in the object with the new attribute template_update_attribute( temp_obj->template, new_attr );
CK_RV key_mgr_generate_key( SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * new_attr = NULL; CK_ULONG i, keyclass, subclass = 0; CK_BBOOL flag; CK_RV rc; if (!sess || !mech || !handle){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } if (!pTemplate && (ulCount != 0)){ OCK_LOG_ERR(ERR_FUNCTION_FAILED); return CKR_FUNCTION_FAILED; } // it's silly but Cryptoki allows the user to specify the CKA_CLASS // in the template. so we have to iterate through the provided template // and make sure that if CKA_CLASS is CKO_SECRET_KEY, if it is present. // // it would have been more logical for Cryptoki to forbid specifying // the CKA_CLASS attribute when generating a key // for (i=0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; if (keyclass != CKO_SECRET_KEY){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } } if (pTemplate[i].type == CKA_KEY_TYPE) subclass = *(CK_ULONG *)pTemplate[i].pValue; } switch (mech->mechanism) { case CKM_DES_KEY_GEN: if (subclass != 0 && subclass != CKK_DES){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DES; break; case CKM_DES3_KEY_GEN: if (subclass != 0 && subclass != CKK_DES3){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DES3; break; #if !(NOCDMF) case CKM_CDMF_KEY_GEN: if (subclass != 0 && subclass != CKK_CDMF){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_CDMF; break; #endif case CKM_SSL3_PRE_MASTER_KEY_GEN: if (subclass != 0 && subclass != CKK_GENERIC_SECRET){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } if (mech->ulParameterLen != sizeof(CK_VERSION)){ OCK_LOG_ERR(ERR_MECHANISM_PARAM_INVALID); return CKR_MECHANISM_PARAM_INVALID; } subclass = CKK_GENERIC_SECRET; break; case CKM_AES_KEY_GEN: if (subclass != 0 && subclass != CKK_AES){ OCK_LOG_ERR(ERR_TEMPLATE_INCONSISTENT); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_AES; break; default: OCK_LOG_ERR(ERR_MECHANISM_INVALID); return CKR_MECHANISM_INVALID; } rc = object_mgr_create_skel( sess, pTemplate, ulCount, MODE_KEYGEN, CKO_SECRET_KEY, subclass, &key_obj ); if (rc != CKR_OK){ OCK_LOG_ERR(ERR_OBJMGR_CREATE_SKEL); goto error; } // at this point, 'key_obj' should contain a skeleton key. depending on // the key type, we may need to extract one or more attributes from // the object prior to generating the key data (ie. variable key length) // switch (mech->mechanism) { case CKM_DES_KEY_GEN: rc = ckm_des_key_gen( key_obj->template );