⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ks_p11.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2004 - 2006 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  */#include "hx_locl.h"RCSID("$Id: ks_p11.c 22071 2007-11-14 20:04:50Z lha $");#ifdef HAVE_DLFCN_H#include <dlfcn.h>#endif#ifdef HAVE_DLOPEN#include "pkcs11.h"struct p11_slot {    int flags;#define P11_SESSION		1#define P11_SESSION_IN_USE	2#define P11_LOGIN_REQ		4#define P11_LOGIN_DONE		8#define P11_TOKEN_PRESENT	16    CK_SESSION_HANDLE session;    CK_SLOT_ID id;    CK_BBOOL token;    char *name;    hx509_certs certs;    char *pin;    struct {	CK_MECHANISM_TYPE_PTR list;	CK_ULONG num;	CK_MECHANISM_INFO_PTR *infos;    } mechs;};struct p11_module {    void *dl_handle;    CK_FUNCTION_LIST_PTR funcs;    CK_ULONG num_slots;    unsigned int refcount;    struct p11_slot *slot;};#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)argsstatic int p11_get_session(hx509_context,			   struct p11_module *,			   struct p11_slot *,			   hx509_lock,			   CK_SESSION_HANDLE *);static int p11_put_session(struct p11_module *,			   struct p11_slot *,			   CK_SESSION_HANDLE);static void p11_release_module(struct p11_module *);static int p11_list_keys(hx509_context,			 struct p11_module *,			 struct p11_slot *, 			 CK_SESSION_HANDLE,			 hx509_lock,			 hx509_certs *);/* * */struct p11_rsa {    struct p11_module *p;    struct p11_slot *slot;    CK_OBJECT_HANDLE private_key;    CK_OBJECT_HANDLE public_key;};static intp11_rsa_public_encrypt(int flen,		       const unsigned char *from,		       unsigned char *to,		       RSA *rsa,		       int padding){    return -1;}static intp11_rsa_public_decrypt(int flen,		       const unsigned char *from,		       unsigned char *to,		       RSA *rsa,		       int padding){    return -1;}static intp11_rsa_private_encrypt(int flen, 			const unsigned char *from,			unsigned char *to,			RSA *rsa,			int padding){    struct p11_rsa *p11rsa = RSA_get_app_data(rsa);    CK_OBJECT_HANDLE key = p11rsa->private_key;    CK_SESSION_HANDLE session;    CK_MECHANISM mechanism;    CK_ULONG ck_sigsize;    int ret;    if (padding != RSA_PKCS1_PADDING)	return -1;    memset(&mechanism, 0, sizeof(mechanism));    mechanism.mechanism = CKM_RSA_PKCS;    ck_sigsize = RSA_size(rsa);    ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);    if (ret)	return -1;    ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key));    if (ret != CKR_OK) {	p11_put_session(p11rsa->p, p11rsa->slot, session);	return -1;    }    ret = P11FUNC(p11rsa->p, Sign, 		  (session, (CK_BYTE *)from, flen, to, &ck_sigsize));    p11_put_session(p11rsa->p, p11rsa->slot, session);    if (ret != CKR_OK)	return -1;    return ck_sigsize;}static intp11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,			RSA * rsa, int padding){    struct p11_rsa *p11rsa = RSA_get_app_data(rsa);    CK_OBJECT_HANDLE key = p11rsa->private_key;    CK_SESSION_HANDLE session;    CK_MECHANISM mechanism;    CK_ULONG ck_sigsize;    int ret;    if (padding != RSA_PKCS1_PADDING)	return -1;    memset(&mechanism, 0, sizeof(mechanism));    mechanism.mechanism = CKM_RSA_PKCS;    ck_sigsize = RSA_size(rsa);    ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);    if (ret)	return -1;    ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key));    if (ret != CKR_OK) {	p11_put_session(p11rsa->p, p11rsa->slot, session);	return -1;    }    ret = P11FUNC(p11rsa->p, Decrypt, 		  (session, (CK_BYTE *)from, flen, to, &ck_sigsize));    p11_put_session(p11rsa->p, p11rsa->slot, session);    if (ret != CKR_OK)	return -1;    return ck_sigsize;}static int p11_rsa_init(RSA *rsa){    return 1;}static intp11_rsa_finish(RSA *rsa){    struct p11_rsa *p11rsa = RSA_get_app_data(rsa);    p11_release_module(p11rsa->p);    free(p11rsa);    return 1;}static const RSA_METHOD p11_rsa_pkcs1_method = {    "hx509 PKCS11 PKCS#1 RSA",    p11_rsa_public_encrypt,    p11_rsa_public_decrypt,    p11_rsa_private_encrypt,    p11_rsa_private_decrypt,    NULL,    NULL,    p11_rsa_init,    p11_rsa_finish,    0,    NULL,    NULL,    NULL};/* * */static intp11_mech_info(hx509_context context,	      struct p11_module *p,	      struct p11_slot *slot,	      int num){    CK_ULONG i;    int ret;    ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i));    if (ret) {	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,			       "Failed to get mech list count for slot %d",			       num);	return HX509_PKCS11_NO_MECH;    }    if (i == 0) {	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,			       "no mech supported for slot %d", num);	return HX509_PKCS11_NO_MECH;    }    slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0]));    if (slot->mechs.list == NULL) {	hx509_set_error_string(context, 0, ENOMEM,			       "out of memory");	return ENOMEM;    }    slot->mechs.num = i;    ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i));    if (ret) {	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,			       "Failed to get mech list for slot %d",			       num);	return HX509_PKCS11_NO_MECH;    }    assert(i == slot->mechs.num);    slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos));    if (slot->mechs.list == NULL) {	hx509_set_error_string(context, 0, ENOMEM,			       "out of memory");	return ENOMEM;    }    for (i = 0; i < slot->mechs.num; i++) {	slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0])));	if (slot->mechs.infos[i] == NULL) {	    hx509_set_error_string(context, 0, ENOMEM,				   "out of memory");	    return ENOMEM;	}	ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i],					    slot->mechs.infos[i]));	if (ret) {	    hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,				   "Failed to get mech info for slot %d",				   num);	    return HX509_PKCS11_NO_MECH;	}    }    return 0;}static intp11_init_slot(hx509_context context, 	      struct p11_module *p,	      hx509_lock lock,	      CK_SLOT_ID id,	      int num,	      struct p11_slot *slot){    CK_SESSION_HANDLE session;    CK_SLOT_INFO slot_info;    CK_TOKEN_INFO token_info;    int ret, i;    slot->certs = NULL;    slot->id = id;    ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info));    if (ret) {	hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED,			       "Failed to init PKCS11 slot %d",			       num);	return HX509_PKCS11_TOKEN_CONFUSED;    }    for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) {	char c = slot_info.slotDescription[i];	if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0')	    continue;	i++;	break;    }    asprintf(&slot->name, "%.*s",	     i, slot_info.slotDescription);    if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)	return 0;    ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info));    if (ret) {	hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN,			       "Failed to init PKCS11 slot %d "			       "with error 0x08x",			       num, ret);	return HX509_PKCS11_NO_TOKEN;    }    slot->flags |= P11_TOKEN_PRESENT;    if (token_info.flags & CKF_LOGIN_REQUIRED)	slot->flags |= P11_LOGIN_REQ;    ret = p11_get_session(context, p, slot, lock, &session);    if (ret)	return ret;    ret = p11_mech_info(context, p, slot, num);    if (ret)	goto out;    ret = p11_list_keys(context, p, slot, session, lock, &slot->certs); out:    p11_put_session(p, slot, session);    return ret;}static intp11_get_session(hx509_context context,		struct p11_module *p,		struct p11_slot *slot,		hx509_lock lock,		CK_SESSION_HANDLE *psession){    CK_RV ret;    if (slot->flags & P11_SESSION_IN_USE)	_hx509_abort("slot already in session");        if (slot->flags & P11_SESSION) {	slot->flags |= P11_SESSION_IN_USE;	*psession = slot->session;	return 0;    }    ret = P11FUNC(p, OpenSession, (slot->id, 				   CKF_SERIAL_SESSION,				   NULL,				   NULL,				   &slot->session));    if (ret != CKR_OK) {	if (context)	    hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION,				   "Failed to OpenSession for slot id %d "				   "with error: 0x%08x",				   (int)slot->id, ret);	return HX509_PKCS11_OPEN_SESSION;    }        slot->flags |= P11_SESSION;        /*      * If we have have to login, and haven't tried before and have a     * prompter or known to work pin code.     *     * This code is very conversative and only uses the prompter in     * the hx509_lock, the reason is that it's bad to try many     * passwords on a pkcs11 token, it might lock up and have to be     * unlocked by a administrator.     *     * XXX try harder to not use pin several times on the same card.     */    if (   (slot->flags & P11_LOGIN_REQ)	&& (slot->flags & P11_LOGIN_DONE) == 0	&& (lock || slot->pin))    {	hx509_prompt prompt;	char pin[20];	char *str;	slot->flags |= P11_LOGIN_DONE;	if (slot->pin == NULL) {	    memset(&prompt, 0, sizeof(prompt));	    asprintf(&str, "PIN code for %s: ", slot->name);	    prompt.prompt = str;	    prompt.type = HX509_PROMPT_TYPE_PASSWORD;	    prompt.reply.data = pin;	    prompt.reply.length = sizeof(pin);	    	    ret = hx509_lock_prompt(lock, &prompt);	    if (ret) {		free(str);		if (context)		    hx509_set_error_string(context, 0, ret,					   "Failed to get pin code for slot "					   "id %d with error: %d",					   (int)slot->id, ret);		return ret;	    }	    free(str);	} else {	    strlcpy(pin, slot->pin, sizeof(pin));	}	ret = P11FUNC(p, Login, (slot->session, CKU_USER,				 (unsigned char*)pin, strlen(pin)));	if (ret != CKR_OK) {	    if (context)		hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN,				       "Failed to login on slot id %d "				       "with error: 0x%08x",				       (int)slot->id, ret);	    p11_put_session(p, slot, slot->session);	    return HX509_PKCS11_LOGIN;	}	if (slot->pin == NULL) {	    slot->pin = strdup(pin);	    if (slot->pin == NULL) {		if (context)		    hx509_set_error_string(context, 0, ENOMEM,					   "out of memory");		p11_put_session(p, slot, slot->session);		return ENOMEM;	    }	}    } else	slot->flags |= P11_LOGIN_DONE;    slot->flags |= P11_SESSION_IN_USE;    *psession = slot->session;    return 0;}static intp11_put_session(struct p11_module *p,		struct p11_slot *slot, 		CK_SESSION_HANDLE session){    if ((slot->flags & P11_SESSION_IN_USE) == 0)	_hx509_abort("slot not in session");    slot->flags &= ~P11_SESSION_IN_USE;    return 0;}static intiterate_entries(hx509_context context,		struct p11_module *p, struct p11_slot *slot,		CK_SESSION_HANDLE session,		CK_ATTRIBUTE *search_data, int num_search_data,		CK_ATTRIBUTE *query, int num_query,		int (*func)(hx509_context,			    struct p11_module *, struct p11_slot *,			    CK_SESSION_HANDLE session,			    CK_OBJECT_HANDLE object,			    void *, CK_ATTRIBUTE *, int), void *ptr){    CK_OBJECT_HANDLE object;    CK_ULONG object_count;    int ret, i;    ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data));    if (ret != CKR_OK) {	return -1;    }    while (1) {	ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count));	if (ret != CKR_OK) {	    return -1;	}	if (object_count == 0)	    break;		for (i = 0; i < num_query; i++)	    query[i].pValue = NULL;	ret = P11FUNC(p, GetAttributeValue, 		      (session, object, query, num_query));	if (ret != CKR_OK) {	    return -1;	}	for (i = 0; i < num_query; i++) {	    query[i].pValue = malloc(query[i].ulValueLen);	    if (query[i].pValue == NULL) {		ret = ENOMEM;		goto out;	    }	}	ret = P11FUNC(p, GetAttributeValue,		      (session, object, query, num_query));	if (ret != CKR_OK) {	    ret = -1;	    goto out;	}		ret = (*func)(context, p, slot, session, object, ptr, query, num_query);	if (ret)	    goto out;	for (i = 0; i < num_query; i++) {	    if (query[i].pValue)		free(query[i].pValue);	    query[i].pValue = NULL;	}    } out:    for (i = 0; i < num_query; i++) {	if (query[i].pValue)	    free(query[i].pValue);	query[i].pValue = NULL;    }    ret = P11FUNC(p, FindObjectsFinal, (session));    if (ret != CKR_OK) {	return -2;    }    return 0;}		static BIGNUM *getattr_bn(struct p11_module *p,	   struct p11_slot *slot,	   CK_SESSION_HANDLE session,	   CK_OBJECT_HANDLE object, 	   unsigned int type){    CK_ATTRIBUTE query;    BIGNUM *bn;    int ret;    query.type = type;    query.pValue = NULL;    query.ulValueLen = 0;    ret = P11FUNC(p, GetAttributeValue, 		  (session, object, &query, 1));    if (ret != CKR_OK)	return NULL;    query.pValue = malloc(query.ulValueLen);    ret = P11FUNC(p, GetAttributeValue, 		  (session, object, &query, 1));    if (ret != CKR_OK) {	free(query.pValue);	return NULL;    }    bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL);    free(query.pValue);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -