11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: ssh-pkcs11.c,v 1.6 2010/06/08 21:32:19 markus Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2010 Markus Friedl. All rights reserved. 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies. 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_TIME_H 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/time.h> 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h> 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <dlfcn.h> 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h" 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define CRYPTOKI_COMPAT 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "pkcs11.h" 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h" 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-pkcs11.h" 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct pkcs11_slotinfo { 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_TOKEN_INFO token; 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_SESSION_HANDLE session; 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int logged_in; 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct pkcs11_provider { 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *name; 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood void *handle; 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *function_list; 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_INFO info; 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG nslots; 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_SLOT_ID *slotlist; 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_slotinfo *slotinfo; 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int valid; 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int refcount; 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_ENTRY(pkcs11_provider) next; 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodTAILQ_HEAD(, pkcs11_provider) pkcs11_providers; 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct pkcs11_key { 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_provider *provider; 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG slotidx; 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int (*orig_finish)(RSA *rsa); 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA_METHOD rsa_method; 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *keyid; 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int keyid_len; 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint pkcs11_interactive = 0; 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_init(int interactive) 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_interactive = interactive; 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_INIT(&pkcs11_providers); 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * finalize a provider shared libarary, it's no longer usable. 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * however, there might still be keys referencing this provider, 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * so the actuall freeing of memory is handled by pkcs11_provider_unref(). 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * this is called when a provider gets unregistered. 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_provider_finalize(struct pkcs11_provider *p) 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG i; 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("pkcs11_provider_finalize: %p refcount %d valid %d", 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p, p->refcount, p->valid); 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!p->valid) 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < p->nslots; i++) { 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p->slotinfo[i].session && 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (rv = p->function_list->C_CloseSession( 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->slotinfo[i].session)) != CKR_OK) 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_CloseSession failed: %lu", rv); 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK) 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Finalize failed: %lu", rv); 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->valid = 0; 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->function_list = NULL; 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dlclose(p->handle); 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * remove a reference to the provider. 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called when a key gets destroyed or when the provider is unregistered. 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_provider_unref(struct pkcs11_provider *p) 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount); 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (--p->refcount <= 0) { 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p->valid) 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("pkcs11_provider_unref: %p still valid", p); 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p->slotlist); 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p->slotinfo); 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p); 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* unregister all providers, keys might still point to the providers */ 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_terminate(void) 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_provider *p; 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) { 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_REMOVE(&pkcs11_providers, p, next); 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_provider_finalize(p); 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_provider_unref(p); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* lookup provider by name */ 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pkcs11_provider * 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_provider_lookup(char *provider_id) 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_provider *p; 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_FOREACH(p, &pkcs11_providers, next) { 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("check %p %s", p, p->name); 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!strcmp(provider_id, p->name)) 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (p); 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (NULL); 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* unregister provider by name */ 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_del_provider(char *provider_id) 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_provider *p; 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_REMOVE(&pkcs11_providers, p, next); 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_provider_finalize(p); 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_provider_unref(p); 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* openssl callback for freeing an RSA key */ 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_rsa_finish(RSA *rsa) 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_key *k11; 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rv = -1; 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((k11 = RSA_get_app_data(rsa)) != NULL) { 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (k11->orig_finish) 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rv = k11->orig_finish(rsa); 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (k11->provider) 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_provider_unref(k11->provider); 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (k11->keyid) 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(k11->keyid); 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(k11); 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (rv); 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* find a single 'obj' for given attributes */ 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG nattr, CK_OBJECT_HANDLE *obj) 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *f; 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_SESSION_HANDLE session; 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG nfound = 0; 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ret = -1; 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood f = p->function_list; 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood session = p->slotinfo[slotidx].session; 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK || 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood nfound != 1) { 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("C_FindObjects failed (nfound %lu nattr %lu): %lu", 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood nfound, nattr, rv); 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = 0; 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_FindObjectsFinal failed: %lu", rv); 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (ret); 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* openssl callback doing the actual signing operation */ 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, 2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int padding) 2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_key *k11; 2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_slotinfo *si; 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *f; 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_OBJECT_HANDLE obj; 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG tlen = 0; 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_BBOOL true_val = CK_TRUE; 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_MECHANISM mech = { 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CKM_RSA_PKCS, NULL_PTR, 0 2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood }; 2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ATTRIBUTE key_filter[] = { 2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood {CKA_CLASS, NULL, sizeof(private_key_class) }, 2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood {CKA_ID, NULL, 0}, 2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood {CKA_SIGN, NULL, sizeof(true_val) } 2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood }; 2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *pin, prompt[1024]; 2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rval = -1; 2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* some compilers complain about non-constant initializer so we 2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood use NULL in CK_ATTRIBUTE above and set the values here */ 2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_filter[0].pValue = &private_key_class; 2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_filter[2].pValue = &true_val; 2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((k11 = RSA_get_app_data(rsa)) == NULL) { 2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("RSA_get_app_data failed for rsa %p", rsa); 2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!k11->provider || !k11->provider->valid) { 2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("no pkcs11 (valid) provider for rsa %p", rsa); 2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood f = k11->provider->function_list; 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood si = &k11->provider->slotinfo[k11->slotidx]; 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!pkcs11_interactive) { 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("need pin"); 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood si->token.label); 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pin = read_passphrase(prompt, RP_ALLOW_EOF); 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pin == NULL) 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); /* bail out */ 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_Login(si->session, CKU_USER, pin, strlen(pin))) 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(pin); 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Login failed: %lu", rv); 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(pin); 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood si->logged_in = 1; 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_filter[1].pValue = k11->keyid; 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_filter[1].ulValueLen = k11->keyid_len; 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* try to find object w/CKA_SIGN first, retry w/o */ 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 && 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) { 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("cannot find private key"); 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_SignInit failed: %lu", rv); 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX handle CKR_BUFFER_TOO_SMALL */ 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tlen = RSA_size(rsa); 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (rv == CKR_OK) 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rval = tlen; 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Sign failed: %lu", rv); 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (rval); 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int padding) 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* redirect private key operations for rsa key to pkcs11 token */ 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ATTRIBUTE *keyid_attrib, RSA *rsa) 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_key *k11; 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const RSA_METHOD *def = RSA_get_default_method(); 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11 = xcalloc(1, sizeof(*k11)); 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->provider = provider; 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood provider->refcount++; /* provider referenced by RSA key */ 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->slotidx = slotidx; 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* identify key object on smartcard */ 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->keyid_len = keyid_attrib->ulValueLen; 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->keyid = xmalloc(k11->keyid_len); 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); 3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->orig_finish = def->finish; 3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); 3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->rsa_method.name = "pkcs11"; 3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt; 3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt; 3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood k11->rsa_method.finish = pkcs11_rsa_finish; 3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA_set_method(rsa, &k11->rsa_method); 3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA_set_app_data(rsa, k11); 3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* remove trailing spaces */ 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodrmspace(char *buf, size_t len) 3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t i; 3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!len) 3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = len - 1; i > 0; i--) 3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (i == len - 1 || buf[i] == ' ') 3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[i] = '\0'; 3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * open a pkcs11 session and login if required. 3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * if pin == NULL we delay login until key use 3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) 3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *f; 3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_SESSION_HANDLE session; 3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int login_required; 3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood f = p->function_list; 3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED; 3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pin && login_required && !strlen(pin)) { 3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("pin required"); 3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| 3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CKF_SERIAL_SESSION, NULL, NULL, &session)) 3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_OpenSession failed: %lu", rv); 3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (login_required && pin) { 3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_Login(session, CKU_USER, pin, strlen(pin))) 3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Login failed: %lu", rv); 3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_CloseSession(session)) != CKR_OK) 3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_CloseSession failed: %lu", rv); 3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->slotinfo[slotidx].logged_in = 1; 3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->slotinfo[slotidx].session = session; 3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * lookup public keys for token in slot identified by slotidx, 3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * add 'wrapped' public keys to the 'keysp' array and increment nkeys. 3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * keysp points to an (possibly empty) array with *nkeys keys. 3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, 3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int *nkeys) 3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *key; 3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA *rsa; 3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i; 3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_OBJECT_HANDLE obj; 3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG nfound; 3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_SESSION_HANDLE session; 3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *f; 4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; 4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ATTRIBUTE pubkey_filter[] = { 4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { CKA_CLASS, NULL, sizeof(pubkey_class) } 4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood }; 4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ATTRIBUTE attribs[] = { 4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { CKA_ID, NULL, 0 }, 4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { CKA_MODULUS, NULL, 0 }, 4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { CKA_PUBLIC_EXPONENT, NULL, 0 } 4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood }; 4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* some compilers complain about non-constant initializer so we 4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood use NULL in CK_ATTRIBUTE above and set the value here */ 4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pubkey_filter[0].pValue = &pubkey_class; 4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood f = p->function_list; 4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood session = p->slotinfo[slotidx].session; 4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* setup a filter the looks for public keys */ 4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjectsInit(session, pubkey_filter, 1)) != CKR_OK) { 4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_FindObjectsInit failed: %lu", rv); 4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (1) { 4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX 3 attributes in attribs[] */ 4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < 3; i++) { 4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[i].pValue = NULL; 4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[i].ulValueLen = 0; 4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK 4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood || nfound == 0) 4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* found a key, so figure out size of the attributes */ 4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) 4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetAttributeValue failed: %lu", rv); 4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* check that none of the attributes are zero length */ 4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (attribs[0].ulValueLen == 0 || 4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[1].ulValueLen == 0 || 4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[2].ulValueLen == 0) { 4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* allocate buffers for attributes */ 4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < 3; i++) 4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[i].pValue = xmalloc(attribs[i].ulValueLen); 4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* retrieve ID, modulus and public exponent of RSA key */ 4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) 4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetAttributeValue failed: %lu", rv); 4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((rsa = RSA_new()) == NULL) { 4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("RSA_new failed"); 4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rsa->n = BN_bin2bn(attribs[1].pValue, 4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[1].ulValueLen, NULL); 4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rsa->e = BN_bin2bn(attribs[2].pValue, 4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attribs[2].ulValueLen, NULL); 4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (rsa->n && rsa->e && 4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { 4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key = key_new(KEY_UNSPEC); 4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key->rsa = rsa; 4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key->type = KEY_RSA; 4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key->flags |= KEY_FLAG_EXT; 4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* expand key array and add key */ 4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *keysp = xrealloc(*keysp, *nkeys + 1, 4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sizeof(Key *)); 4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (*keysp)[*nkeys] = key; 4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *nkeys = *nkeys + 1; 4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("have %d keys", *nkeys); 4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood RSA_free(rsa); 4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < 3; i++) 4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(attribs[i].pValue); 4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) 4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_FindObjectsFinal failed: %lu", rv); 4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* register a new provider, fails if provider already exists */ 4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) 4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int nkeys, need_finalize = 0; 4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_provider *p = NULL; 4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood void *handle = NULL; 4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); 4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_RV rv; 4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_FUNCTION_LIST *f = NULL; 4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_TOKEN_INFO *token; 4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CK_ULONG i; 4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *keyp = NULL; 4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pkcs11_provider_lookup(provider_id) != NULL) { 4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("provider already registered: %s", provider_id); 4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* open shared pkcs11-libarary */ 4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { 5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("dlopen %s failed: %s", provider_id, dlerror()); 5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { 5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("dlsym(C_GetFunctionList) failed: %s", dlerror()); 5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p = xcalloc(1, sizeof(*p)); 5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->name = xstrdup(provider_id); 5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->handle = handle; 5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* setup the pkcs11 callbacks */ 5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { 5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetFunctionList failed: %lu", rv); 5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->function_list = f; 5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_Initialize(NULL)) != CKR_OK) { 5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Initialize failed: %lu", rv); 5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood need_finalize = 1; 5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { 5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetInfo failed: %lu", rv); 5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); 5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); 5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("manufacturerID <%s> cryptokiVersion %d.%d" 5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " libraryDescription <%s> libraryVersion %d.%d", 5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.manufacturerID, 5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.cryptokiVersion.major, 5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.cryptokiVersion.minor, 5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.libraryDescription, 5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.libraryVersion.major, 5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->info.libraryVersion.minor); 5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { 5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetSlotList failed: %lu", rv); 5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p->nslots == 0) { 5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("no slots"); 5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); 5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) 5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetSlotList failed: %lu", rv); 5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto fail; 5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); 5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->valid = 1; 5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood nkeys = 0; 5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < p->nslots; i++) { 5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood token = &p->slotinfo[i].token; 5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) 5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood != CKR_OK) { 5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_GetTokenInfo failed: %lu", rv); 5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(token->label, sizeof(token->label)); 5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(token->manufacturerID, sizeof(token->manufacturerID)); 5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(token->model, sizeof(token->model)); 5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmspace(token->serialNumber, sizeof(token->serialNumber)); 5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("label <%s> manufacturerID <%s> model <%s> serial <%s>" 5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " flags 0x%lx", 5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood token->label, token->manufacturerID, token->model, 5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood token->serialNumber, token->flags); 5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* open session, login with pin and retrieve public keys */ 5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pkcs11_open_session(p, i, pin) == 0) 5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_fetch_keys(p, i, keyp, &nkeys); 5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (nkeys > 0) { 5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); 5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood p->refcount++; /* add to provider list */ 5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (nkeys); 5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("no keys"); 5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* don't add the provider, since it does not have any keys */ 5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfail: 5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) 5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("C_Finalize failed: %lu", rv); 5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p) { 5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p->slotlist) 5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p->slotlist); 5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p->slotinfo) 5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p->slotinfo); 5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p); 5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (handle) 5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dlclose(handle); 5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_init(int interactive) 5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpkcs11_terminate(void) 6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* ENABLE_PKCS11 */ 608