📄 framework-pkcs15.c
字号:
/* * framework-pkcs15.c: PKCS#15 framework and related objects * * Copyright (C) 2002 Timo Ter鋝 <timo.teras@iki.fi> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdlib.h>#include <string.h>#include "sc-pkcs11.h"#ifdef USE_PKCS15_INIT#include "opensc/pkcs15-init.h"#endif#define MAX_CACHE_PIN 32struct pkcs15_slot_data { struct sc_pkcs15_object *auth_obj; struct { u8 value[MAX_CACHE_PIN]; unsigned int len; } pin[2];};#define slot_data(p) ((struct pkcs15_slot_data *) p)#define slot_data_auth(p) (slot_data(p)->auth_obj)#define slot_data_pin_info(p) (slot_data_auth(p)? \ (struct sc_pkcs15_pin_info *) slot_data_auth(p)->data : NULL)#define check_attribute_buffer(attr,size) \ if (attr->pValue == NULL_PTR) { \ attr->ulValueLen = size; \ return CKR_OK; \ } \ if (attr->ulValueLen < size) { \ attr->ulValueLen = size; \ return CKR_BUFFER_TOO_SMALL; \ } \ attr->ulValueLen = size;#define MAX_OBJECTS 64struct pkcs15_fw_data { struct sc_pkcs15_card * p15_card; struct pkcs15_any_object * objects[MAX_OBJECTS]; unsigned int num_objects; unsigned int locked;};struct pkcs15_any_object { struct sc_pkcs11_object base; unsigned int refcount; size_t size; struct sc_pkcs15_object * p15_object; struct pkcs15_pubkey_object * related_pubkey; struct pkcs15_cert_object * related_cert; struct pkcs15_prkey_object * related_privkey;};struct pkcs15_cert_object { struct pkcs15_any_object base; struct sc_pkcs15_cert_info * cert_info; struct sc_pkcs15_cert * cert_data;};#define cert_flags base.base.flags#define cert_p15obj base.p15_object#define cert_pubkey base.related_pubkey#define cert_issuer base.related_certstruct pkcs15_prkey_object { struct pkcs15_any_object base; struct sc_pkcs15_prkey_info * prv_info;};#define prv_flags base.base.flags#define prv_p15obj base.p15_object#define prv_pubkey base.related_pubkey#define prv_cert base.related_cert#define prv_next base.related_privkeystruct pkcs15_pubkey_object { struct pkcs15_any_object base; struct sc_pkcs15_pubkey_info * pub_info; /* NULL for key extracted from cert */ struct sc_pkcs15_pubkey * pub_data;};#define pub_flags base.base.flags#define pub_p15obj base.p15_object#define pub_cert base.related_cert#define __p15_type(obj) (((obj) && (obj)->p15_object)? ((obj)->p15_object->type) : -1)#define is_privkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PRKEY_RSA)#define is_pubkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PUBKEY_RSA)#define is_cert(obj) (__p15_type(obj) == SC_PKCS15_TYPE_CERT_X509)extern struct sc_pkcs11_object_ops pkcs15_cert_ops;extern struct sc_pkcs11_object_ops pkcs15_prkey_ops;extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops;static int __pkcs15_release_object(struct pkcs15_any_object *);static int register_mechanisms(struct sc_pkcs11_card *p11card);static CK_RV get_public_exponent(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);static CK_RV get_modulus(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);static CK_RV get_modulus_bits(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);static void cache_pin(void *, int, const void *, size_t);static int revalidate_pin(struct pkcs15_slot_data *data, struct sc_pkcs11_session *ses);static int lock_card(struct pkcs15_fw_data *);static int unlock_card(struct pkcs15_fw_data *);/* PKCS#15 Framework */static CK_RV pkcs15_bind(struct sc_pkcs11_card *p11card){ struct pkcs15_fw_data *fw_data; int rc; if (!(fw_data = (struct pkcs15_fw_data *) calloc(1, sizeof(*fw_data)))) return CKR_HOST_MEMORY; p11card->fw_data = fw_data; rc = sc_pkcs15_bind(p11card->card, &fw_data->p15_card); sc_debug(context, "Binding to PKCS#15, rc=%d\n", rc); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); return register_mechanisms(p11card);}static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; unsigned int i; int rc; for (i = 0; i < fw_data->num_objects; i++) __pkcs15_release_object(fw_data->objects[i]); unlock_card(fw_data); rc = sc_pkcs15_unbind(fw_data->p15_card); return sc_to_cryptoki_error(rc, p11card->reader);}static void pkcs15_init_token_info(struct sc_pkcs15_card *card, CK_TOKEN_INFO_PTR pToken){ int sn_start = strlen(card->serial_number) - 16; strcpy_bp(pToken->manufacturerID, card->manufacturer_id, 32); strcpy_bp(pToken->model, "PKCS #15 SCard", 16); /* Take the last 16 chars of the serial number (if the are more then 16). _Assuming_ that the serial number is a Big Endian counter, this will assure that the serial within each type of card will be unique in pkcs11 (at least for the first 16^16 cards :-) */ if (sn_start < 0) sn_start = 0; strcpy_bp(pToken->serialNumber, card->serial_number + sn_start, 16); pToken->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE; pToken->ulSessionCount = 0; /* FIXME */ pToken->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE; pToken->ulRwSessionCount = 0; /* FIXME */ pToken->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; pToken->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; pToken->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; pToken->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; pToken->hardwareVersion.major = 1; pToken->hardwareVersion.minor = 0; pToken->firmwareVersion.major = 1; pToken->firmwareVersion.minor = 0;}static int__pkcs15_create_object(struct pkcs15_fw_data *fw_data, struct pkcs15_any_object **result, struct sc_pkcs15_object *p15_object, struct sc_pkcs11_object_ops *ops, size_t size){ struct pkcs15_any_object *obj; if (fw_data->num_objects >= MAX_OBJECTS) return SC_ERROR_TOO_MANY_OBJECTS; if (!(obj = (struct pkcs15_any_object *) calloc(1, size))) return SC_ERROR_OUT_OF_MEMORY; fw_data->objects[fw_data->num_objects++] = obj; obj->base.ops = ops; obj->p15_object = p15_object; obj->refcount = 1; obj->size = size; *result = obj; return 0;}static int__pkcs15_release_object(struct pkcs15_any_object *obj){ if (--(obj->refcount) != 0) return obj->refcount; memset(obj, 0xAA, obj->size); free(obj); return 0;}static int__pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_object *cert, struct pkcs15_any_object **cert_object){ struct sc_pkcs15_cert_info *p15_info; struct sc_pkcs15_cert *p15_cert; struct pkcs15_cert_object *object; struct pkcs15_pubkey_object *obj2; int rv; p15_info = (struct sc_pkcs15_cert_info *) cert->data; if ((rv = sc_pkcs15_read_certificate(fw_data->p15_card, p15_info, &p15_cert) < 0)) return rv; /* Certificate object */ rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object, cert, &pkcs15_cert_ops, sizeof(struct pkcs15_cert_object)); if (rv < 0) return rv; object->cert_info = p15_info; object->cert_data = p15_cert; /* Corresponding public key */ rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &obj2, NULL, &pkcs15_pubkey_ops, sizeof(struct pkcs15_pubkey_object)); if (rv < 0) return rv; obj2->pub_data = &p15_cert->key; obj2->pub_cert = object; object->cert_pubkey = obj2; if (cert_object != NULL) *cert_object = (struct pkcs15_any_object *) object; return 0;}static int__pkcs15_create_pubkey_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_object *pubkey, struct pkcs15_any_object **pubkey_object){ struct pkcs15_pubkey_object *object; struct sc_pkcs15_pubkey *p15_key; int rv; /* Read public key from card */ if ((rv = sc_pkcs15_read_pubkey(fw_data->p15_card, pubkey, &p15_key)) < 0) return rv; /* Public key object */ rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object, pubkey, &pkcs15_pubkey_ops, sizeof(struct pkcs15_pubkey_object)); if (rv >= 0) { object->pub_info = (struct sc_pkcs15_pubkey_info *) pubkey->data; object->pub_data = p15_key; } if (pubkey_object != NULL) *pubkey_object = (struct pkcs15_any_object *) object; return rv;}static int__pkcs15_create_prkey_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_object *prkey, struct pkcs15_any_object **prkey_object){ struct pkcs15_prkey_object *object; int rv; rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object, prkey, &pkcs15_prkey_ops, sizeof(struct pkcs15_prkey_object)); if (rv >= 0) object->prv_info = (struct sc_pkcs15_prkey_info *) prkey->data; if (prkey_object != NULL) *prkey_object = (struct pkcs15_any_object *) object; return 0;}static intpkcs15_create_pkcs11_objects(struct pkcs15_fw_data *fw_data, int p15_type, const char *name, int (*create)(struct pkcs15_fw_data *, struct sc_pkcs15_object *, struct pkcs15_any_object **any_object)){ struct sc_pkcs15_object *p15_object[MAX_OBJECTS]; int i, count, rv; rv = count = sc_pkcs15_get_objects(fw_data->p15_card, p15_type, p15_object, MAX_OBJECTS); if (rv >= 0) { sc_debug(context, "Found %d %s%s\n", count, name, (count == 1)? "" : "s"); } for (i = 0; rv >= 0 && i < count; i++) { rv = create(fw_data, p15_object[i], NULL); } return count;}static void__pkcs15_prkey_bind_related(struct pkcs15_fw_data *fw_data, struct pkcs15_prkey_object *pk){ sc_pkcs15_id_t *id = &pk->prv_info->id; unsigned int i; for (i = 0; i < fw_data->num_objects; i++) { struct pkcs15_any_object *obj = fw_data->objects[i]; if (obj->base.flags & SC_PKCS11_OBJECT_HIDDEN) continue; if (is_privkey(obj) && obj != (struct pkcs15_any_object *) pk) { /* merge private keys with the same ID and * different usage bits */ struct pkcs15_prkey_object *other, **pp; other = (struct pkcs15_prkey_object *) obj; if (sc_pkcs15_compare_id(&other->prv_info->id, id)) { obj->base.flags |= SC_PKCS11_OBJECT_HIDDEN; for (pp = &pk->prv_next; *pp; pp = &(*pp)->prv_next) ; *pp = (struct pkcs15_prkey_object *) obj; } } else if (is_cert(obj) && !pk->prv_cert) { struct pkcs15_cert_object *cert; cert = (struct pkcs15_cert_object *) obj; if (sc_pkcs15_compare_id(&cert->cert_info->id, id)) pk->prv_cert = cert; } else if (is_pubkey(obj) && !pk->prv_pubkey) { struct pkcs15_pubkey_object *pubkey; pubkey = (struct pkcs15_pubkey_object *) obj; if (sc_pkcs15_compare_id(&pubkey->pub_info->id, id)) pk->prv_pubkey = pubkey; } }}static void__pkcs15_cert_bind_related(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object *cert){ struct sc_pkcs15_cert *c1 = cert->cert_data, *c2; unsigned int i; /* Loop over all certificates see if we find the certificate of * the issuer */ for (i = 0; i < fw_data->num_objects; i++) { struct pkcs15_any_object *obj = fw_data->objects[i]; if (!is_cert(obj) || obj == (struct pkcs15_any_object *) cert) continue; c2 = ((struct pkcs15_cert_object *) obj)->cert_data; if (!c1 || !c2 || !c1->issuer_len || !c2->subject_len) continue; if (c1->issuer_len == c2->subject_len && !memcmp(c1->issuer, c2->subject, c1->issuer_len)) { cert->cert_issuer = (struct pkcs15_cert_object *) obj; return; } }}static voidpkcs15_bind_related_objects(struct pkcs15_fw_data *fw_data){ unsigned int i; /* Loop over all private keys and attached related certificate * and/or public key */ for (i = 0; i < fw_data->num_objects; i++) { struct pkcs15_any_object *obj = fw_data->objects[i]; if (obj->base.flags & SC_PKCS11_OBJECT_HIDDEN) continue; if (is_privkey(obj)) { __pkcs15_prkey_bind_related(fw_data, (struct pkcs15_prkey_object *) obj); } else if (is_cert(obj)) { __pkcs15_cert_bind_related(fw_data, (struct pkcs15_cert_object *) obj); } }}static intpool_is_present(struct sc_pkcs11_pool *pool, struct pkcs15_any_object *obj){ struct sc_pkcs11_pool_item *item; for (item = pool->head; item != NULL; item = item->next) { if (obj == (struct pkcs15_any_object *) item->item) return 1; } return 0;}static voidpkcs15_add_object(struct sc_pkcs11_slot *slot, struct pkcs15_any_object *obj, CK_OBJECT_HANDLE_PTR pHandle){ if (obj == NULL || (obj->base.flags & (SC_PKCS11_OBJECT_HIDDEN | SC_PKCS11_OBJECT_RECURS))) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -