/* Session manipulation */ CK_RV session_start_operation(struct sc_pkcs11_session * session, int type, sc_pkcs11_mechanism_type_t * mech, struct sc_pkcs11_operation ** operation) { sc_pkcs11_operation_t *op; if (context == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; LOG_FUNC_CALLED(context); sc_log(context, "Session 0x%lx, type %d", session->handle, type); if (type < 0 || type >= SC_PKCS11_OPERATION_MAX) return CKR_ARGUMENTS_BAD; if (session->operation[type] != NULL) return CKR_OPERATION_ACTIVE; if (!(op = sc_pkcs11_new_operation(session, mech))) return CKR_HOST_MEMORY; session->operation[type] = op; if (operation) *operation = op; return CKR_OK; }
/* * Initialize a signature operation */ static CK_RV sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation, struct sc_pkcs11_object *key) { struct hash_signature_info *info; struct signature_data *data; CK_RV rv; int can_do_it = 0; LOG_FUNC_CALLED(context); if (!(data = calloc(1, sizeof(*data)))) LOG_FUNC_RETURN(context, CKR_HOST_MEMORY); data->info = NULL; data->key = key; if (key->ops->can_do) { rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN); if (rv == CKR_OK) { /* Mechanism recognised and can be performed by pkcs#15 card */ can_do_it = 1; } else if (rv == CKR_FUNCTION_NOT_SUPPORTED) { /* Mechanism not recognised by pkcs#15 card */ can_do_it = 0; } else { /* Mechanism recognised but cannot be performed by pkcs#15 card, or some general error. */ free(data); LOG_FUNC_RETURN(context, rv); } } /* If this is a signature with hash operation, * and card cannot perform itself signature with hash operation, * set up the hash operation */ info = (struct hash_signature_info *) operation->type->mech_data; if (info != NULL && !can_do_it) { /* Initialize hash operation */ data->md = sc_pkcs11_new_operation(operation->session, info->hash_type); if (data->md == NULL) rv = CKR_HOST_MEMORY; else rv = info->hash_type->md_init(data->md); if (rv != CKR_OK) { sc_pkcs11_release_operation(&data->md); free(data); LOG_FUNC_RETURN(context, rv); } data->info = info; } operation->priv_data = data; LOG_FUNC_RETURN(context, CKR_OK); }
/* * Initialize a signature operation */ static CK_RV sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation, struct sc_pkcs11_object *key) { struct hash_signature_info *info; struct signature_data *data; int rv; if (!(data = calloc(1, sizeof(*data)))) return CKR_HOST_MEMORY; data->info = NULL; data->key = key; /* If this is a verify with hash operation, set up the * hash operation */ info = (struct hash_signature_info *) operation->type->mech_data; if (info != NULL) { /* Initialize hash operation */ data->md = sc_pkcs11_new_operation(operation->session, info->hash_type); if (data->md == NULL) rv = CKR_HOST_MEMORY; else rv = info->hash_type->md_init(data->md); if (rv != CKR_OK) { sc_pkcs11_release_operation(&data->md); free(data); return rv; } data->info = info; } operation->priv_data = data; return CKR_OK; }