📄 mechanism.c
字号:
/* * Generic handling of PKCS11 mechanisms * * Copyright (C) 2002 Olaf Kirch <okir@lst.de> */#include <stdlib.h>#include <string.h>#include "sc-pkcs11.h"/* Also used for verification data */struct hash_signature_info { CK_MECHANISM_TYPE mech; CK_MECHANISM_TYPE hash_mech; CK_MECHANISM_TYPE sign_mech; sc_pkcs11_mechanism_type_t *hash_type; sc_pkcs11_mechanism_type_t *sign_type;};/* Also used for verification data */struct signature_data { struct sc_pkcs11_object *key; struct hash_signature_info *info; sc_pkcs11_operation_t * md; CK_BYTE buffer[4096/8]; unsigned int buffer_len;};/* * Register a mechanism */CK_RVsc_pkcs11_register_mechanism(struct sc_pkcs11_card *p11card, sc_pkcs11_mechanism_type_t *mt){ sc_pkcs11_mechanism_type_t **p; if (mt == NULL) return CKR_HOST_MEMORY; p = (sc_pkcs11_mechanism_type_t **) realloc(p11card->mechanisms, (p11card->nmechanisms + 2) * sizeof(*p)); if (p == NULL) return CKR_HOST_MEMORY; p11card->mechanisms = p; p[p11card->nmechanisms++] = mt; p[p11card->nmechanisms] = NULL; return CKR_OK;}/* * Look up a mechanism */sc_pkcs11_mechanism_type_t *sc_pkcs11_find_mechanism(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mech, int flags){ sc_pkcs11_mechanism_type_t *mt; unsigned int n; for (n = 0; n < p11card->nmechanisms; n++) { mt = p11card->mechanisms[n]; if (mt && mt->mech == mech && ((mt->mech_info.flags & flags) == flags)) return mt; } return NULL;}/* * Query mechanisms. * All of this is greatly simplified by having the framework * register all supported mechanisms at initialization * time. */CK_RVsc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE_PTR pList, CK_ULONG_PTR pulCount){ sc_pkcs11_mechanism_type_t *mt; unsigned int n, count = 0; int rv; for (n = 0; n < p11card->nmechanisms; n++) { if (!(mt = p11card->mechanisms[n])) continue; if (count < *pulCount && pList) pList[count] = mt->mech; count++; } rv = CKR_OK; if (pList && count > *pulCount) rv = CKR_BUFFER_TOO_SMALL; *pulCount = count; return rv;}CK_RVsc_pkcs11_get_mechanism_info(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mechanism, CK_MECHANISM_INFO_PTR pInfo){ sc_pkcs11_mechanism_type_t *mt; if (!(mt = sc_pkcs11_find_mechanism(p11card, mechanism, 0))) return CKR_MECHANISM_INVALID; memcpy(pInfo, &mt->mech_info, sizeof(*pInfo)); return CKR_OK;}/* * Create/destroy operation handle */sc_pkcs11_operation_t *sc_pkcs11_new_operation(sc_pkcs11_session_t *session, sc_pkcs11_mechanism_type_t *type){ sc_pkcs11_operation_t *res; res = (sc_pkcs11_operation_t *) calloc(1, type->obj_size); if (res) { res->session = session; res->type = type; } return res;}voidsc_pkcs11_release_operation(sc_pkcs11_operation_t **ptr){ sc_pkcs11_operation_t *operation = *ptr; if (!operation) return; if (operation->type && operation->type->release) operation->type->release(operation); memset(operation, 0, sizeof(*operation)); free(operation); *ptr = NULL;}CK_RVsc_pkcs11_md_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechanism){ struct sc_pkcs11_card *p11card; sc_pkcs11_operation_t *operation; sc_pkcs11_mechanism_type_t *mt; int rv; if (!session || !session->slot || !(p11card = session->slot->card)) return CKR_ARGUMENTS_BAD; /* See if we support this mechanism type */ mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_DIGEST); if (mt == NULL) return CKR_MECHANISM_INVALID; rv = session_start_operation(session, SC_PKCS11_OPERATION_DIGEST, mt, &operation); if (rv != CKR_OK) return rv; memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM)); rv = mt->md_init(operation); if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST); return rv;}CK_RVsc_pkcs11_md_update(struct sc_pkcs11_session *session, CK_BYTE_PTR pData, CK_ULONG ulDataLen){ sc_pkcs11_operation_t *op; int rv; rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op); if (rv != CKR_OK) goto done; rv = op->type->md_update(op, pData, ulDataLen);done: if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST); return rv;}CK_RVsc_pkcs11_md_final(struct sc_pkcs11_session *session, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen){ sc_pkcs11_operation_t *op; int rv; rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op); if (rv != CKR_OK) return rv; /* This is a request for the digest length */ if (pData == NULL) *pulDataLen = 0; rv = op->type->md_final(op, pData, pulDataLen); if (rv == CKR_BUFFER_TOO_SMALL) return pData == NULL ? CKR_OK : rv; session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST); return rv;}/* * Initialize a signing context. When we get here, we know * the key object is capable of signing _something_ */CK_RVsc_pkcs11_sign_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechanism, struct sc_pkcs11_object *key, CK_MECHANISM_TYPE key_type){ struct sc_pkcs11_card *p11card; sc_pkcs11_operation_t *operation; sc_pkcs11_mechanism_type_t *mt; int rv; if (!session || !session->slot || !(p11card = session->slot->card)) return CKR_ARGUMENTS_BAD; /* See if we support this mechanism type */ mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_SIGN); if (mt == NULL) return CKR_MECHANISM_INVALID; /* See if compatible with key type */ if (mt->key_type != key_type) return CKR_KEY_TYPE_INCONSISTENT; rv = session_start_operation(session, SC_PKCS11_OPERATION_SIGN, mt, &operation); if (rv != CKR_OK) return rv; memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM)); rv = mt->sign_init(operation, key); if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_SIGN); return rv;}CK_RVsc_pkcs11_sign_update(struct sc_pkcs11_session *session, CK_BYTE_PTR pData, CK_ULONG ulDataLen){ sc_pkcs11_operation_t *op; int rv; rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op); if (rv != CKR_OK) return rv; if (op->type->sign_update == NULL) { rv = CKR_KEY_TYPE_INCONSISTENT; goto done; } rv = op->type->sign_update(op, pData, ulDataLen);done: if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_SIGN); return rv;}CK_RVsc_pkcs11_sign_final(struct sc_pkcs11_session *session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen){ sc_pkcs11_operation_t *op; int rv; rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op); if (rv != CKR_OK) return rv; /* Bail out for signature mechanisms that don't do hashing */ if (op->type->sign_final == NULL) { rv = CKR_KEY_TYPE_INCONSISTENT; goto done; } rv = op->type->sign_final(op, pSignature, pulSignatureLen);done: if (rv != CKR_BUFFER_TOO_SMALL && pSignature != NULL) session_stop_operation(session, SC_PKCS11_OPERATION_SIGN); return rv;}CK_RVsc_pkcs11_sign_size(struct sc_pkcs11_session *session, CK_ULONG_PTR pLength){ sc_pkcs11_operation_t *op; int rv; rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op); if (rv != CKR_OK) return rv; /* Bail out for signature mechanisms that don't do hashing */ if (op->type->sign_size == NULL) { rv = CKR_KEY_TYPE_INCONSISTENT; goto done; } rv = op->type->sign_size(op, pLength);done: if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_SIGN); return rv;}/* * Initialize a signature operation */static CK_RVsc_pkcs11_signature_init(sc_pkcs11_operation_t *operation, struct sc_pkcs11_object *key){ struct hash_signature_info *info; struct signature_data *data; int rv; if (!(data = (struct signature_data *) calloc(1, sizeof(*data)))) return CKR_HOST_MEMORY; data->info = NULL; data->key = key; /* If this is a signature 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -