pk11.c revision c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5
/*
* 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/.
*/
#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 scan_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;
}
scan_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);
}
#define PK11_TRACE(fmt) \
#define PK11_TRACEM(mech) \
static void
scan_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;
PK11_TRACE("no CKF_RNG\n");
goto try_rsa;
}
if (rand_token == NULL)
rand_token = token;
&mechInfo);
}
&mechInfo);
#ifndef PK11_MD5_DISABLE
#endif
}
&mechInfo);
}
&mechInfo);
}
&mechInfo);
}
if (bad)
goto try_dsa;
if (best_rsa_token == NULL)
&mechInfo);
#ifndef PK11_DSA_PARAMETER_GEN_SKIP
#endif
}
&mechInfo);
}
}
if (bad)
goto try_dh;
#ifndef PK11_DSA_DISABLE
if (best_dsa_token == NULL)
#endif
&mechInfo);
}
&mechInfo);
#ifndef PK11_DH_PKCS_PARAMETER_GEN_SKIP
#endif
}
&mechInfo);
}
if (bad)
goto try_digest;
#ifndef PK11_DH_DISABLE
if (best_dh_token == NULL)
#endif
#ifndef PK11_MD5_DISABLE
#endif
}
}
}
}
}
}
#if !defined(PK11_MD5_DISABLE) && !defined(PK11_MD5_HMAC_REPLACE)
#endif
}
#ifndef PK11_SHA_1_HMAC_REPLACE
#endif
}
#ifndef PK11_SHA224_HMAC_REPLACE
#endif
}
#ifndef PK11_SHA256_HMAC_REPLACE
#endif
}
#ifndef PK11_SHA384_HMAC_REPLACE
#endif
}
#ifndef PK11_SHA512_HMAC_REPLACE
#endif
}
if (!bad) {
if (digest_token == NULL)
}
/* ECDSA requires digest */
&mechInfo);
}
}
if (bad)
goto try_gost;
if (best_ec_token == NULL)
/* does GOST require digest too? */
}
&mechInfo);
}
&mechInfo);
}
if (bad)
goto try_aes;
if (best_gost_token == NULL)
}
if (bad)
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");
}
if (!first)
printf(",");
printf("AES");
}
printf(")\n");
}
}