pk11.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Portions copyright (c) 2008 Nominet UK. 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
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This product includes software developed by the OpenSSL Project for
* use in the OpenSSL Toolkit (http://www.openssl.org/).
*
* This project also referenced hw_pkcs11-0.9.7b.patch written by
* Afchine Madjlessi.
*/
/*
* ====================================================================
* Copyright (c) 2000-2001 The OpenSSL Project. 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
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED 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 OpenSSL PROJECT OR
* ITS 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.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* $Id$ */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <isc/platform.h>
#include <pk11/internal.h>
#include <pkcs11/cryptoki.h>
/* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */
#ifndef PINLEN
#define PINLEN 256
#endif
#ifndef PK11_NO_LOGERR
#define PK11_NO_LOGERR 1
#endif
static isc_int32_t allocsize = 0;
typedef struct pk11_session pk11_session_t;
typedef struct pk11_token pk11_token_t;
struct pk11_session {
unsigned int magic;
};
struct pk11_token {
unsigned int magic;
unsigned int operations;
char name[32];
char manuf[32];
char model[16];
char serial[16];
};
static pk11_token_t *rand_token;
static pk11_token_t *best_rsa_token;
static pk11_token_t *best_dsa_token;
static pk11_token_t *best_dh_token;
static pk11_token_t *digest_token;
static pk11_token_t *best_ec_token;
static pk11_token_t *best_gost_token;
static pk11_token_t *aes_token;
static isc_result_t free_all_sessions(void);
static void choose_slots(void);
static isc_mutex_t alloclock;
static isc_mutex_t sessionlock;
static pk11_sessionlist_t actives;
static CK_C_INITIALIZE_ARGS pk11_init_args = {
NULL_PTR, /* CreateMutex */
NULL_PTR, /* DestroyMutex */
NULL_PTR, /* LockMutex */
NULL_PTR, /* UnlockMutex */
CKF_OS_LOCKING_OK, /* flags */
NULL_PTR, /* pReserved */
};
#ifndef PK11_LIB_LOCATION
#define PK11_LIB_LOCATION "unknown_provider"
#endif
#ifndef WIN32
static const char *lib_name = PK11_LIB_LOCATION;
#else
#endif
void
pk11_set_lib_name(const char *name) {
}
const char *
pk11_get_lib_name(void) {
return (lib_name);
}
static void
initialize(void) {
char *pk11_provider;
if (pk11_provider != NULL)
}
void *
void *ptr;
else {
}
return (ptr);
}
void
else {
}
}
if (initialized) {
return (ISC_R_SUCCESS);
} else {
LOCK(&sessionlock);
}
/* Initialize the CRYPTOKI library */
if (rv == 0xfe) {
goto unlock;
}
goto unlock;
}
choose_slots();
#ifdef PKCS11CRYPTO
if (rand_token == NULL) {
goto unlock;
}
if (digest_token == NULL) {
goto unlock;
}
#if defined(AES_CC)
goto unlock;
}
#endif
#endif /* PKCS11CRYPTO */
return (result);
}
pk11_finalize(void) {
ret = free_all_sessions();
(void) pkcs_C_Finalize(NULL_PTR);
if (token == rand_token)
rand_token = NULL;
if (token == best_rsa_token)
if (token == best_dsa_token)
if (token == best_dh_token)
if (token == digest_token)
digest_token = NULL;
if (token == best_ec_token)
if (token == best_gost_token)
}
return (ret);
}
if ((ret != ISC_R_SUCCESS) &&
(ret != PK11_R_NODIGESTSERVICE) &&
(ret != PK11_R_NOAESSERVICE))
return (ret);
return (ISC_R_SUCCESS);
else
return (DST_R_CRYPTOFAILURE);
}
#define SEEDSIZE 1024
void
pk11_rand_seed_fromfile(const char *randomfile) {
if ((ret != ISC_R_SUCCESS) &&
(ret != PK11_R_NODIGESTSERVICE) &&
(ret != PK11_R_NOAESSERVICE))
return;
if (ret != ISC_R_SUCCESS)
goto cleanup;
if (ret!= ISC_R_SUCCESS)
goto cleanup;
if (ret!= ISC_R_SUCCESS)
goto cleanup;
(void) isc_stdio_close(stream);
}
{
#ifdef PKCS11CRYPTO
#else
#endif
#ifdef PKCS11CRYPTO
if (ret == PK11_R_NORANDOMSERVICE ||
ret == PK11_R_NODIGESTSERVICE ||
ret == PK11_R_NOAESSERVICE) {
if (need_services)
return (ret);
service_ret = ret;
}
else
#endif /* PKCS11CRYPTO */
if (ret != ISC_R_SUCCESS)
return (ret);
LOCK(&sessionlock);
/* wait for initialization to finish */
switch(optype) {
#ifdef PKCS11CRYPTO
case OP_RAND:
token = rand_token;
break;
case OP_DIGEST:
break;
case OP_AES:
break;
case OP_ANY:
break;
break;
#endif
default:
break;
#ifdef PKCS11CRYPTO
return (ISC_R_NOTFOUND);
#endif
break;
}
return (ISC_R_NOTFOUND);
/* Override the token's PIN */
return ISC_R_RANGE;
}
LOCK(&sessionlock);
if (logon)
return (ret);
}
return (ISC_R_NOMEMORY);
LOCK(&sessionlock);
#ifdef PKCS11CRYPTO
if (ret == ISC_R_SUCCESS)
ret = service_ret;
#endif
return (ret);
}
void
return;
LOCK(&sessionlock);
return;
}
LOCK(&sessionlock);
}
static isc_result_t
free_all_sessions(void) {
if (oret != ISC_R_SUCCESS)
}
if (!ISC_LIST_EMPTY(actives)) {
if (oret != ISC_R_SUCCESS)
}
return (ret);
}
static isc_result_t
ret = ISC_R_SUCCESS;
LOCK(&sessionlock);
while (!ISC_LIST_EMPTY(*slist)) {
}
LOCK(&sessionlock);
}
return (ret);
}
static isc_result_t
{
if (rw)
flags += CKF_RW_SESSION;
return (DST_R_CRYPTOFAILURE);
return (ISC_R_SUCCESS);
}
static isc_result_t
LOCK(&sessionlock);
ret = ISC_R_NOPERM;
#if PK11_NO_LOGERR
"pkcs_C_Login", rv);
#endif
} else
}
return (ret);
}
static void
choose_slots(void) {
unsigned int i;
slotCount = 0;
/* it's not an error if we didn't find any providers */
if (slotCount == 0)
return;
for (i = 0; i < slotCount; i++) {
continue;
goto try_rsa;
if (rand_token == NULL)
rand_token = token;
&mechInfo);
goto try_dsa;
&mechInfo);
goto try_dsa;
&mechInfo);
goto try_dsa;
&mechInfo);
goto try_dsa;
&mechInfo);
goto try_dsa;
if (best_rsa_token == NULL)
&mechInfo);
goto try_dh;
&mechInfo);
goto try_dh;
goto try_dh;
if (best_dsa_token == NULL)
#ifdef notdef
&mechInfo);
goto try_digest;
#endif
&mechInfo);
goto try_digest;
&mechInfo);
goto try_digest;
if (best_dh_token == NULL)
continue;
continue;
continue;
continue;
continue;
continue;
#ifdef PKCS11CRYPTOWITHHMAC
continue;
#endif
continue;
continue;
continue;
continue;
continue;
if (digest_token == NULL)
/* ECDSA requires digest */
&mechInfo);
goto try_gost;
goto try_gost;
if (best_ec_token == NULL)
/* does GOST require digest too? */
goto try_aes;
&mechInfo);
goto try_aes;
&mechInfo);
goto try_aes;
if (best_gost_token == NULL)
continue;
}
}
switch (optype) {
case OP_RAND:
token = rand_token;
break;
case OP_RSA:
break;
case OP_DSA:
break;
case OP_DH:
break;
case OP_DIGEST:
break;
case OP_EC:
break;
case OP_GOST:
break;
case OP_AES:
break;
default:
break;
}
return (0);
}
unsigned int
unsigned int bitcnt, i;
if (bytecnt == 0)
return (0);
for (i = 0; i < bytecnt; i++) {
if (top == 0) {
bitcnt -= 8;
continue;
}
if (top & 0x80)
return (bitcnt);
if (top & 0x40)
return (bitcnt - 1);
if (top & 0x20)
return (bitcnt - 2);
if (top & 0x10)
return (bitcnt - 3);
if (top & 0x08)
return (bitcnt - 4);
if (top & 0x04)
return (bitcnt - 5);
if (top & 0x02)
return (bitcnt - 6);
if (top & 0x01)
return (bitcnt - 7);
break;
}
INSIST(0);
}
}
return (NULL);
return (next);
}
return (attr);
return (NULL);
}
static char *
char *p, *c;
unsigned char v;
for (p = c = x; p[0] != '\0'; p++, c++) {
switch (p[0]) {
case '%':
v = 0;
switch (p[1]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
v = (p[1] - '0') << 4;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
v = (p[1] - 'A' + 10) << 4;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
v = (p[1] - 'a' + 10) << 4;
break;
default:
return (NULL);
}
switch (p[2]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
v |= (p[2] - '0') & 0x0f;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
v = (p[2] - 'A' + 10) & 0x0f;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
v = (p[2] - 'a' + 10) & 0x0f;
break;
default:
return (NULL);
}
p += 2;
*c = (char) v;
(*len)++;
break;
default:
*c = *p;
(*len)++;
}
}
return (x);
}
static isc_boolean_t
char buf[32];
}
static CK_ATTRIBUTE *
return (NULL);
}
return (NULL);
}
}
return (attr);
}
{
/* get values to work on */
return (ISC_R_NOMEMORY);
/* get the URI scheme */
if (p == NULL)
*p++ = '\0';
/* get attributes */
a = na;
p = strchr(a, ';');
if (p == NULL) {
/* last attribute */
} else {
*p++ = '\0';
na = p;
}
p = strchr(a, '=');
if (p != NULL) {
*p++ = '\0';
v = p;
} else
v = a;
l = 0;
v = percent_decode(v, &l);
if (v == NULL)
if ((a == v) || (strcmp(a, "object") == 0)) {
/* object: CKA_LABEL */
} else if (strcmp(a, "token") == 0) {
/* token: CK_TOKEN_INFO label */
break;
} else if (strcmp(a, "manufacturer") == 0) {
/* manufacturer: CK_TOKEN_INFO manufacturerID */
break;
} else if (strcmp(a, "serial") == 0) {
/* serial: CK_TOKEN_INFO serialNumber */
break;
} else if (strcmp(a, "model") == 0) {
/* model: CK_TOKEN_INFO model */
break;
} else if (strcmp(a, "library-manufacturer") == 0) {
/* ignored */
} else if (strcmp(a, "library-description") == 0) {
/* ignored */
} else if (strcmp(a, "library-version") == 0) {
/* ignored */
} else if (strcmp(a, "object-type") == 0) {
/* object-type: CKA_CLASS */
/* only private makes sense */
if (strcmp(v, "private") != 0)
} else if (strcmp(a, "id") == 0) {
/* id: CKA_ID */
} else if (strcmp(a, "pin-source") == 0) {
/* pin-source: PIN */
if (ret != ISC_R_SUCCESS)
goto err;
goto err;
if (l > PINLEN)
if (ret != ISC_R_SUCCESS)
goto err;
} else
}
}
if (gotpin) {
}
ret = ISC_R_SUCCESS;
err:
(void) isc_stdio_close(stream);
return (ret);
}
void
{
}
void
pk11_dump_tokens(void)
{
printf("DEFAULTS\n");
printf("\nTOKEN\n");
if (!first)
printf(",");
printf("RAND");
}
if (!first)
printf(",");
printf("RSA");
}
if (!first)
printf(",");
printf("DSA");
}
if (!first)
printf(",");
printf("DH");
}
if (!first)
printf(",");
printf("DIGEST");
}
if (!first)
printf(",");
printf("EC");
}
printf(")\n");
}
}