new sslengines implementation with pkcs11 and opensc backend.

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1097 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
aj 2003-05-12 20:21:08 +00:00
parent b1e4c88aec
commit 496232d9b9
19 changed files with 3420 additions and 0 deletions

View File

@ -0,0 +1,6 @@
.deps
.libs
*.lo
*.la
Makefile
Makefile.in

View File

@ -0,0 +1,25 @@
libdir = @libdir@/opensc
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = engine_opensc.c engine_opensc.h hw_opensc.c \
engine_pkcs11.c engine_pkcs11.h hw_pkcs11.c \
p11_attr.c p11_cert.c p11_err.c p11_key.c p11_load.c p11_misc.c \
p11_rsa.c p11_slot.c pkcs11-internal.h \
test_engine.s
if HAVE_ENGINE
lib_LTLIBRARIES=engine_opensc.la engine_pkcs11.la
endif
engine_opensc_la_SOURCES = hw_opensc.c engine_opensc.c
engine_opensc_la_CFLAGS = -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -DENGINE_DYNAMIC_SUPPORT -DSHA1_ASM -DMD5_ASM -DRMD160_ASM @CFLAGS_OPENSC@
engine_opensc_la_LIBADD = @LIBCRYPTOA@ @LIBOPENSC@
engine_opensc_la_LDFLAGS = -Wl,-Bsymbolic -module -avoid-version
engine_pkcs11_la_SOURCES = hw_pkcs11.c engine_pkcs11.c \
p11_attr.c p11_cert.c p11_err.c p11_key.c p11_load.c p11_misc.c \
p11_rsa.c p11_slot.c
engine_pkcs11_la_CFLAGS = -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -DENGINE_DYNAMIC_SUPPORT -DSHA1_ASM -DMD5_ASM -DRMD160_ASM @CFLAGS_OPENSC@
engine_pkcs11_la_LIBADD = @LIBCRYPTOA@ ../pkcs11/.libs/libpkcs11.a
engine_pkcs11_la_LDFLAGS = -Wl,-Bsymbolic -module -avoid-version

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
* Copyright (c) 2001 Markus Friedl.
* Copyright (c) 2003 Kevin Stefanik
*
* 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.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include "opensc/opensc.h"
#include "opensc/pkcs15.h"
#include "engine_opensc.h"
/* static state info one card/reader at a time */
static int quiet=1;
static int sc_reader_id= 0;
static sc_context_t *ctx = NULL;
static sc_card_t *card = NULL;
static sc_pkcs15_card_t *p15card = NULL;
static char* sc_pin=NULL;
int opensc_finish() {
if (p15card) {
sc_pkcs15_unbind(p15card);
p15card = NULL;
}
if (card) {
sc_disconnect_card(card, 0);
card = NULL;
}
if (ctx) {
sc_release_context(ctx);
ctx = NULL;
}
return 1;
}
int opensc_init() {
int r=0;
if(!quiet)
fprintf(stderr,"initializing engine");
r = sc_establish_context(&ctx, "openssl");
if (r)
goto err;
r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card);
if (r)
goto err;
r = sc_pkcs15_bind(card, &p15card);
if (r)
goto err;
return 1;
err:
/* need to do engine stuff? */
fprintf(stderr, "error: %d",r);
opensc_finish();
return 0;
}
int
opensc_rsa_finish(RSA* rsa) {
struct sc_pkcs15_key_id *key_id;
key_id = RSA_get_app_data(rsa);
free(key_id); // which free?
if(sc_pin) {free(sc_pin);}
return 1;
}
BIGNUM *sc_bignum_t_to_BIGNUM(sc_pkcs15_bignum_t* bignum, BIGNUM* BN) {
BN_bin2bn( (unsigned char *) bignum->data, bignum->len, BN);
return BN;
}
void sc_set_pubkey_data(EVP_PKEY* key_out, sc_pkcs15_pubkey_t* pubkey) {
key_out->pkey.rsa->n=sc_bignum_t_to_BIGNUM(&(pubkey->u.rsa.modulus),BN_new());
key_out->pkey.rsa->e=sc_bignum_t_to_BIGNUM(&(pubkey->u.rsa.exponent),BN_new());
}
/* private key operations */
int
sc_prkey_op_init(const RSA *rsa, struct sc_pkcs15_object **key_obj_out)
{
int r;
struct sc_pkcs15_object *key_obj;
struct sc_pkcs15_prkey_info *key;
struct sc_pkcs15_id* key_id;
struct sc_pkcs15_object *pin_obj;
struct sc_pkcs15_pin_info *pin;
key_id = (struct sc_pkcs15_id *) RSA_get_app_data(rsa);
if(key_id==NULL) {
fprintf(stderr,"key not loaded yet");
return -1;
}
if (p15card == NULL) {
opensc_finish();
r = opensc_init(NULL);
if (r) {
fprintf(stderr,"SmartCard init failed: %s", sc_strerror(r));
goto err;
}
}
r = sc_pkcs15_find_prkey_by_id(p15card, key_id , &key_obj);
if (r) {
fprintf(stderr,"Unable to find private key from SmartCard: %s",
sc_strerror(r));
goto err;
}
key = key_obj->data;
r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id,
&pin_obj);
if (r) {
fprintf(stderr,"Unable to find PIN object from SmartCard: %s",
sc_strerror(r));
goto err;
}
pin = pin_obj->data;
r = sc_lock(card);
if (r) {
fprintf(stderr,"Unable to lock smartcard: %s", sc_strerror(r));
goto err;
}
if (sc_pin != NULL) {
r = sc_pkcs15_verify_pin(p15card, pin, sc_pin,
strlen(sc_pin));
if (r) {
sc_unlock(card);
fprintf(stderr,"PIN code verification failed: %s",
sc_strerror(r));
goto err;
}
} else {
fprintf(stderr,"Warning: PIN not verified");
}
*key_obj_out = key_obj;
return 0;
err:
return -1;
}
EVP_PKEY *opensc_load_public_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) {
int r;
struct sc_pkcs15_id* id;
struct sc_pkcs15_object *obj;
sc_pkcs15_pubkey_t *pubkey = NULL;
sc_pkcs15_cert_t *cert = NULL;
EVP_PKEY* key_out=NULL;
if(!quiet)
fprintf(stderr,"Loading public key!\n");
id=malloc(sizeof(struct sc_pkcs15_id));
id->len = SC_PKCS15_MAX_ID_SIZE;
sc_pkcs15_hex_string_to_id(s_key_id, id);
r = sc_pkcs15_find_pubkey_by_id(p15card, id, &obj);
if (r >= 0) {
// if (!quiet)
printf("Reading public key with ID '%s'\n", s_key_id);
r = sc_pkcs15_read_pubkey(p15card, obj, &pubkey);
} else if (r == SC_ERROR_OBJECT_NOT_FOUND) {
/* No pubkey - try if there's a certificate */
r = sc_pkcs15_find_cert_by_id(p15card, id, &obj);
if (r >= 0) {
// if (!quiet)
printf("Reading certificate with ID '%s'\n", s_key_id);
r = sc_pkcs15_read_certificate(p15card,
(sc_pkcs15_cert_info_t *) obj->data,
&cert);
}
if (r >= 0)
pubkey = &cert->key;
}
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
fprintf(stderr, "Public key with ID '%s' not found.\n", s_key_id);
return NULL;
}
if (r < 0) {
fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
return NULL;
}
// now, set EVP_PKEY data from pubkey object
key_out=EVP_PKEY_new();
if(!key_out)
{fprintf(stderr, "failed to create new EVP_PKEY\n"); return NULL;};
EVP_PKEY_assign_RSA(key_out,RSA_new_method(e));
//RSA_set_method(keyout->rsa, sc_get_rsa_method());
key_out->pkey.rsa->flags|=RSA_FLAG_EXT_PKEY||RSA_FLAG_SIGN_VER;// needed?
RSA_set_app_data(key_out->pkey.rsa, id);
sc_set_pubkey_data(key_out, pubkey);
if (cert)
sc_pkcs15_free_certificate(cert);
else if (pubkey)
sc_pkcs15_free_pubkey(pubkey);
return key_out;
};
char* get_pin(UI_METHOD* ui_method, char* sc_pin, int maxlen) {
UI* ui;
ui=UI_new();
UI_set_method(ui,ui_method);
if(!UI_add_input_string(ui, "SmartCard Password: ", 0, sc_pin, 1, maxlen)) {
fprintf(stderr, "UI_add_input_string failed");
UI_free(ui); return NULL; }
if(!UI_process(ui)) {
fprintf(stderr, "UI_process failed"); return NULL;}
UI_free(ui);
return sc_pin;
}
EVP_PKEY *opensc_load_private_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) {
EVP_PKEY* key_out;
if(!quiet)
fprintf(stderr,"Loading private key!");
if(sc_pin) {free(sc_pin); sc_pin=NULL;}
key_out=opensc_load_public_key(e, s_key_id, ui_method, callback_data);
sc_pin=malloc(12);
get_pin(ui_method,sc_pin,12); // do this here, when storing sc_pin in RSA
//memset(sc_pin,0x0,12);
//free(sc_pin);
if(!key_out) {
fprintf(stderr,"Failed to get private key");
return NULL;
}
return key_out;
//err:
// opensc_close();
// return NULL;
}
int
sc_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
int padding)
{
struct sc_pkcs15_object *key_obj;
int r;
if (padding != RSA_PKCS1_PADDING)
return -1;
r = sc_prkey_op_init(rsa, &key_obj);
if (r)
return -1;
r = sc_pkcs15_decipher(p15card, key_obj, 0, from, flen, to, flen);
sc_unlock(card);
if (r < 0) {
fprintf(stderr,"sc_pkcs15_decipher() failed: %s", sc_strerror(r));
goto err;
}
return r;
err:
//sc_close();
return -1;
}
int
sc_sign(int type, const u_char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
{
struct sc_pkcs15_object *key_obj;
int r;
unsigned long flags = 0;
if(!quiet)
fprintf(stderr,"signing with type %d\n", type);
r = sc_prkey_op_init(rsa, &key_obj);
if (r)
return -1;
/* FIXME: length of sigret correct? */
/* FIXME: check 'type' and modify flags accordingly */
flags |= SC_ALGORITHM_RSA_PAD_PKCS1 ;
if(type==NID_sha1) flags|=SC_ALGORITHM_RSA_HASH_SHA1;
if(type==NID_md5) flags|=SC_ALGORITHM_RSA_HASH_MD5;
// SC_ALGORITHM_RSA_HASH_SHA1;
r = sc_pkcs15_compute_signature(p15card, key_obj, flags,
m, m_len, sigret, RSA_size(rsa));
sc_unlock(card);
if (r < 0) {
fprintf(stderr,"sc_pkcs15_compute_signature() failed: %s",
sc_strerror(r));
goto err;
}
*siglen = r;
return 1;
err:
//sc_close();
return 0;
}
int
sc_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
int padding)
{
fprintf(stderr,"Private key encryption not supported");
return -1;
}

View File

@ -0,0 +1,18 @@
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
int opensc_finish();
int opensc_init();
EVP_PKEY *opensc_load_public_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) ;
EVP_PKEY *opensc_load_private_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) ;
int sc_private_decrypt(int flen, const u_char *from, u_char *to,
RSA *rsa, int padding);
int sc_sign(int type, const u_char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
int sc_private_encrypt(int flen, const u_char *from, u_char *to,
RSA *rsa, int padding);
int opensc_rsa_finish(RSA* rsa) ;

View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
* Copyright (c) 2001 Markus Friedl.
* Copyright (c) 2002 Olaf Kirch
* Copyright (c) 2003 Kevin Stefanik
*
* 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.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include "pkcs11-internal.h"
#include "engine_pkcs11.h"
#define fail(msg) { fprintf(stderr,msg); return NULL;}
PKCS11_CTX *ctx;
char* pin;
int quiet=1;
char *module = "opensc-pkcs11.so";
int set_module(const char *modulename) {
module=modulename;
return 1;
}
char* get_pin(UI_METHOD* ui_method, char* sc_pin, int maxlen) {
UI* ui;
ui=UI_new();
UI_set_method(ui,ui_method);
if(!UI_add_input_string(ui, "SmartCard Password: ", 0, sc_pin, 1, maxlen)) {
fprintf(stderr, "UI_add_input_string failed");
UI_free(ui); return NULL; }
if(!UI_process(ui)) {
fprintf(stderr, "UI_process failed"); return NULL;}
UI_free(ui);
return sc_pin;
}
int pkcs11_finish() {
if (ctx) {
PKCS11_CTX_free(ctx);
}
return 1;
}
int pkcs11_init() {
int r=0;
if(!quiet)
fprintf(stderr,"initializing engine");
ctx = PKCS11_CTX_new();
if (PKCS11_CTX_load(ctx, module) < 0)
fail("unable to load module");
return 1;
}
int
pkcs11_rsa_finish(RSA* rsa) {
if(pin) {free(pin);}
// need to free RSA_ex_data?
return 1;
}
EVP_PKEY *pkcs11_load_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data, int private) {
PKCS11_SLOT *slot_list, *slot;
PKCS11_TOKEN *tok;
PKCS11_KEY *keys;
PKCS11_CERT *certs;
EVP_PKEY *pk;
unsigned int count, n, m;
char flags[64];
int logged_in = 0;
// if(pin) {free(pin); pin=NULL;} // keep cached key?
if (PKCS11_enumerate_slots(ctx, &slot_list, &count) < 0)
fail("failed to enumerate slots");
printf("Found %u slot%s\n", count, (count <= 1)? "" : "s");
again:
for (n = 0; n < count; n++) {
slot = slot_list + n;
flags[0] = '\0';
if (slot->token) {
if (!slot->token->initialized)
strcat(flags, "uninitialized, ");
else if (!slot->token->userPinSet)
strcat(flags, "no pin, ");
if (slot->token->loginRequired)
strcat(flags, "login, ");
if (slot->token->readOnly)
strcat(flags, "ro, ");
} else {
strcpy(flags, "no token");
}
if ((m = strlen(flags)) != 0) {
flags[m-2] = '\0';
}
printf("[%u] %-25.25s %-16s", n, slot->description, flags);
if (slot->token) {
printf(" (%s)",
slot->token->label[0]?
slot->token->label : "no label");
}
printf("\n");
}
if (!(slot = PKCS11_find_token(ctx)))
fail("didn't find any tokens");
tok = slot->token;
if (!tok->initialized) {
printf("Found uninitialized token; \n");
return NULL;
}
if (private && !tok->userPinSet && !tok->readOnly) {
printf("Found slot without user PIN\n");
return NULL;
}
printf("Found slot: %s\n", slot->description);
printf("Found token: %s\n", slot->token->label);
if (PKCS11_enumerate_certs(tok, &certs, &count))
fail("unable to enumerate certificates");
printf("Found %u certificate%s:\n", count, (count <= 1)? "" : "s");
for (n = 0; n < count; n++) {
PKCS11_CERT *c = certs + n;
char *dn = NULL;
printf(" %2u %s", n+1,
c->label);
if (c->x509)
dn = X509_NAME_oneline(X509_get_subject_name(c->x509), NULL, 0);
if (dn) {
printf(" (%s)", dn);
OPENSSL_free(dn);
}
printf("\n");
}
while (1) {
if (PKCS11_enumerate_keys(tok, &keys, &count))
fail("unable to enumerate keys");
if (count)
break;
if (logged_in || !tok->loginRequired)
break;
if (pin == NULL) {
pin=malloc(12);
get_pin(ui_method,pin,12);
}
if (PKCS11_login(slot, 0, pin))
fail("Card login failed");
logged_in++;
}
if (count == 0) {
printf("No keys found.\n");
return NULL;
}
printf("Found %u key%s:\n", count, (count <= 1)? "" : "s");
for (n = 0; n < count; n++) {
PKCS11_KEY *k = keys + n;
printf(" %2u %c%c %s\n", n+1,
k->private? 'P' : ' ',
k->needLogin? 'L' : ' ',
k->label);
}
if (count == 0)
return NULL;
if(private) {
pk = PKCS11_get_private_key(&keys[0]);
} else {
// pk = PKCS11_get_public_key(&keys[0]);
// need a get_public_key?
pk = PKCS11_get_private_key(&keys[0]);
}
return pk;
}
EVP_PKEY *pkcs11_load_public_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) {
EVP_PKEY *pk;
pk=pkcs11_load_key(e, s_key_id, ui_method, callback_data, 0);
if (pk == NULL)
fail("PKCS11_load_public_key returned NULL");
return pk;
}
EVP_PKEY *pkcs11_load_private_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) {
EVP_PKEY* pk;
pk=pkcs11_load_key(e, s_key_id, ui_method, callback_data, 1);
if (pk == NULL)
fail("PKCS11_get_private_key returned NULL");
return pk;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
* Copyright (c) 2001 Markus Friedl.
* Copyright (c) 2003 Kevin Stefanik
*
* 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.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
int set_module(const char *modulename) ;
int pkcs11_finish();
int pkcs11_init();
int pkcs11_rsa_finish(RSA* rsa);
EVP_PKEY *pkcs11_load_public_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data);
EVP_PKEY *pkcs11_load_private_key(ENGINE *e, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data) ;
// defined in p11_rsa.c
RSA_METHOD * pkcs11_get_rsa_method();

218
src/sslengines/hw_opensc.c Normal file
View File

@ -0,0 +1,218 @@
/* crypto/engine/hw_opensc.c */
/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
* project 2000.
* Copied/modified by Kevin Stefanik (kstef@mtppi.org) for the OpenSC
* project 2003.
*/
/* ====================================================================
* Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
* Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org)
*
* 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. 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).
*
*/
//#include "cryptlib.h"
#include <stdio.h>
#include <string.h>
#include <openssl/engine.h>
#ifndef ENGINE_CMD_BASE
#error did not get engine.h
#endif
#include <openssl/crypto.h>
#include <openssl/dso.h>
#include "opensc/opensc.h"
#include "opensc/pkcs15.h"
#include "engine_opensc.h"
#define OPENSC_ENGINE_ID "opensc"
#define OPENSC_ENGINE_NAME "opensc engine"
#define CMD_SO_PATH ENGINE_CMD_BASE
static int opensc_engine_destroy(ENGINE *e);
static int opensc_engine_init(ENGINE *e);
static int opensc_engine_finish(ENGINE *e);
static int opensc_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
/* The definitions for control commands specific to this engine */
/* need to add function to pass in reader id? or user reader:key as key id string? */
static const ENGINE_CMD_DEFN opensc_cmd_defns[] = {
{CMD_SO_PATH,
"SO_PATH",
"Specifies the path to the 'opensc-engine' shared library",
ENGINE_CMD_FLAG_STRING},
{0, NULL, NULL, 0}
};
static int opensc_engine_finish(ENGINE *e) {
// opensc_close();
return opensc_finish();
}
static int
opensc_engine_init(ENGINE *e)
{
return opensc_init();
}
/* Destructor */
static int opensc_engine_destroy(ENGINE *e)
{
return 1;
}
static int opensc_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
{
//int initialised = ((opensc_dso == NULL) ? 0 : 1);
switch(cmd)
{
default:
break;
}
return 0;
}
/* set up default rsa_meth_st with overloaded rsa functions */
/* the actual implementation needs to be in another object */
static int (*orig_finish)(RSA* rsa) ;
static int
opensc_engine_rsa_finish(RSA* rsa) {
opensc_rsa_finish(rsa);
if (orig_finish)
orig_finish(rsa);
return 1;
}
static RSA_METHOD * sc_get_rsa_method(void)
{
static RSA_METHOD smart_rsa;
const RSA_METHOD *def = RSA_get_default_method();
/* use the OpenSSL version */
memcpy(&smart_rsa, def, sizeof(smart_rsa));
smart_rsa.name = "opensc";
/* overload */
smart_rsa.rsa_priv_enc = sc_private_encrypt;
smart_rsa.rsa_priv_dec = sc_private_decrypt;
smart_rsa.rsa_sign = sc_sign;
/* save original */
orig_finish = def->finish;
smart_rsa.finish = opensc_engine_rsa_finish;
/* set flags for sign version */
smart_rsa.flags|=RSA_FLAG_SIGN_VER;
return &smart_rsa;
}
/* This internal function is used by ENGINE_opensc() and possibly by the
* "dynamic" ENGINE support too */
static int bind_helper(ENGINE *e)
{
if(
!ENGINE_set_id(e, OPENSC_ENGINE_ID) ||
!ENGINE_set_destroy_function(e, opensc_engine_destroy) ||
!ENGINE_set_init_function(e, opensc_engine_init) ||
!ENGINE_set_finish_function(e, opensc_engine_finish) ||
!ENGINE_set_ctrl_function(e, opensc_engine_ctrl) ||
!ENGINE_set_cmd_defns(e, opensc_cmd_defns) ||
!ENGINE_set_name(e, OPENSC_ENGINE_NAME) ||
#ifndef OPENSSL_NO_RSA
!ENGINE_set_RSA(e, sc_get_rsa_method())||
#endif
#ifndef OPENSSL_NO_DSA
!ENGINE_set_DSA(e, DSA_get_default_method()) ||
#endif
#ifndef OPENSSL_NO_DH
!ENGINE_set_DH(e, DH_get_default_method()) ||
#endif
!ENGINE_set_RAND(e, RAND_SSLeay()) ||
#if 0
!ENGINE_set_BN_mod_exp(e, BN_mod_exp) ||
#endif
!ENGINE_set_load_pubkey_function(e, opensc_load_public_key ) ||
!ENGINE_set_load_privkey_function(e, opensc_load_private_key) )
{
return 0;
} else {
return 1;
}
}
static int bind_fn(ENGINE *e, const char *id)
{
if(id && (strcmp(id, OPENSC_ENGINE_ID) != 0))
{fprintf(stderr, "bad engine id");return 0;}
if(!bind_helper(e))
{fprintf(stderr, "bind failed"); return 0;}
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)

189
src/sslengines/hw_pkcs11.c Normal file
View File

@ -0,0 +1,189 @@
/* crypto/engine/hw_pkcs11.c */
/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
* project 2000.
* Copied/modified by Kevin Stefanik (kstef@mtppi.org) for the OpenSC
* project 2003.
*/
/* ====================================================================
* Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
* Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org)
*
* 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. 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).
*
*/
//#include "cryptlib.h"
#include <stdio.h>
#include <string.h>
#include <openssl/engine.h>
#ifndef ENGINE_CMD_BASE
#error did not get engine.h
#endif
#include <openssl/crypto.h>
#include <openssl/dso.h>
#include "engine_pkcs11.h"
#define PKCS11_ENGINE_ID "pkcs11"
#define PKCS11_ENGINE_NAME "pkcs11 engine"
#define CMD_SO_PATH ENGINE_CMD_BASE
#define CMD_MODULE_PATH (ENGINE_CMD_BASE+1)
static int pkcs11_engine_destroy(ENGINE *e);
static int pkcs11_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
/* The definitions for control commands specific to this engine */
/* need to add function to pass in reader id? or user reader:key as key id string? */
static const ENGINE_CMD_DEFN pkcs11_cmd_defns[] = {
{CMD_SO_PATH,
"SO_PATH",
"Specifies the path to the 'pkcs11-engine' shared library",
ENGINE_CMD_FLAG_STRING},
{CMD_MODULE_PATH,
"MODULE_PATH",
"Specifies the path to the pkcs11 module shared library",
ENGINE_CMD_FLAG_STRING},
{0, NULL, NULL, 0}
};
/* Destructor */
static int pkcs11_engine_destroy(ENGINE *e)
{
return 1;
}
static int pkcs11_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
{
//int initialised = ((pkcs11_dso == NULL) ? 0 : 1);
switch(cmd)
{
case CMD_MODULE_PATH:
return set_module((const char *)p);
default:
break;
}
return 0;
}
/* set up default rsa_meth_st with overloaded rsa functions */
/* the actual implementation needs to be in another object */
static int (*orig_finish)(RSA* rsa) ;
static int
pkcs11_engine_rsa_finish(RSA* rsa) {
pkcs11_rsa_finish(rsa);
if (orig_finish)
orig_finish(rsa);
return 1;
}
/* This internal function is used by ENGINE_pkcs11() and possibly by the
* "dynamic" ENGINE support too */
static int bind_helper(ENGINE *e)
{
if(
!ENGINE_set_id(e, PKCS11_ENGINE_ID) ||
!ENGINE_set_destroy_function(e, pkcs11_engine_destroy) ||
!ENGINE_set_init_function(e, pkcs11_init) ||
!ENGINE_set_finish_function(e, pkcs11_finish) ||
!ENGINE_set_ctrl_function(e, pkcs11_engine_ctrl) ||
!ENGINE_set_cmd_defns(e, pkcs11_cmd_defns) ||
!ENGINE_set_name(e, PKCS11_ENGINE_NAME) ||
#ifndef OPENSSL_NO_RSA
!ENGINE_set_RSA(e, pkcs11_get_rsa_method())||
#endif
#ifndef OPENSSL_NO_DSA
!ENGINE_set_DSA(e, DSA_get_default_method()) ||
#endif
#ifndef OPENSSL_NO_DH
!ENGINE_set_DH(e, DH_get_default_method()) ||
#endif
!ENGINE_set_RAND(e, RAND_SSLeay()) ||
#if 0
!ENGINE_set_BN_mod_exp(e, BN_mod_exp) ||
#endif
!ENGINE_set_load_pubkey_function(e, pkcs11_load_public_key ) ||
!ENGINE_set_load_privkey_function(e, pkcs11_load_private_key) )
{
return 0;
} else {
return 1;
}
}
static int bind_fn(ENGINE *e, const char *id)
{
if(id && (strcmp(id, PKCS11_ENGINE_ID) != 0))
{fprintf(stderr, "bad engine id");return 0;}
if(!bind_helper(e))
{fprintf(stderr, "bind failed"); return 0;}
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)

View File

@ -0,0 +1,28 @@
/*
*
* libpkcs11.h: OpenSC project's PKCS#11 link library header
*
* Copyright (C) 2002 Timo Teräs <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
*/
extern void *C_LoadModule(const char *name,
CK_FUNCTION_LIST_PTR_PTR);
extern CK_RV C_UnloadModule(void *);

137
src/sslengines/p11_attr.c Normal file
View File

@ -0,0 +1,137 @@
/*
* PKCS11 attribute querying.
*
* The number of layers we stack on top of each other here
* is frightening.
*
* Copyright (C) 2002, Olaf Kirch <okir@lst.de>
*/
#include <assert.h>
#include "pkcs11-internal.h"
static int pkcs11_getattr_int(PKCS11_CTX *, CK_SESSION_HANDLE,
CK_OBJECT_HANDLE, CK_ATTRIBUTE_TYPE,
void *, size_t *);
/*
* Query pkcs11 attributes
*/
static int
pkcs11_getattr_int(PKCS11_CTX *ctx, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE o, CK_ATTRIBUTE_TYPE type, void *value, size_t *size)
{
CK_ATTRIBUTE templ;
int rv;
templ.type = type;
templ.pValue = value;
templ.ulValueLen = *size;
rv = CRYPTOKI_call(ctx, C_GetAttributeValue(session, o, &templ, 1));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_GETATTR, rv);
*size = templ.ulValueLen;
return 0;
}
int
pkcs11_getattr_var(PKCS11_TOKEN *token, CK_OBJECT_HANDLE object,
unsigned int type, void *value, size_t *size)
{
return pkcs11_getattr_int(TOKEN2CTX(token),
PRIVSLOT(TOKEN2SLOT(token))->session,
object, type, value, size);
}
int
pkcs11_getattr(PKCS11_TOKEN *token, CK_OBJECT_HANDLE object,
unsigned int type, void *value, size_t size)
{
return pkcs11_getattr_var(token, object, type, value, &size);
}
int
pkcs11_getattr_s(PKCS11_TOKEN *token, CK_OBJECT_HANDLE object,
unsigned int type, void *value, size_t size)
{
memset(value, 0, size);
return pkcs11_getattr_var(token, object, type, value, &size);
}
int
pkcs11_getattr_bn(PKCS11_TOKEN *token, CK_OBJECT_HANDLE object,
unsigned int type, BIGNUM **bn)
{
CK_BYTE binary[4196 / 8];
size_t size = sizeof(binary);
if (pkcs11_getattr_var(token, object, type, binary, &size))
return -1;
if (size == -1) {
PKCS11err(PKCS11_F_PKCS11_GETATTR,
pkcs11_map_err(CKR_ATTRIBUTE_TYPE_INVALID));
return -1;
}
*bn = BN_bin2bn(binary, size, NULL);
return *bn? 0 : -1;
}
/*
* Add attributes to template
*/
void
pkcs11_addattr(CK_ATTRIBUTE_PTR ap, int type, const void *data, size_t size)
{
ap->type = type;
ap->pValue = malloc(size);
memcpy(ap->pValue, data, size);
ap->ulValueLen = size;
}
/* In PKCS11, virtually every integer is a CK_ULONG */
void
pkcs11_addattr_int(CK_ATTRIBUTE_PTR ap, int type, unsigned long value)
{
CK_ULONG ulValue = value;
pkcs11_addattr(ap, type, &ulValue, sizeof(ulValue));
}
void
pkcs11_addattr_s(CK_ATTRIBUTE_PTR ap, int type, const char *s)
{
pkcs11_addattr(ap, type, s, s? strlen(s) + 1 : 0);
}
void
pkcs11_addattr_bn(CK_ATTRIBUTE_PTR ap, int type, const BIGNUM *bn)
{
unsigned char temp[1024];
unsigned int n;
assert (BN_num_bytes(bn) <= sizeof(temp));
n = BN_bn2bin(bn, temp);
pkcs11_addattr(ap, type, temp, n);
}
void
pkcs11_addattr_obj(CK_ATTRIBUTE_PTR ap, int type, pkcs11_i2d_fn enc, void *obj)
{
unsigned char *p;
ap->type = type;
ap->ulValueLen = enc(obj, NULL);
ap->pValue = p = malloc(ap->ulValueLen);
enc(obj, &p);
}
void
pkcs11_zap_attrs(CK_ATTRIBUTE_PTR ap, unsigned int n)
{
while (n--) {
if (ap[n].pValue)
free(ap[n].pValue);
}
}

235
src/sslengines/p11_cert.c Normal file
View File

@ -0,0 +1,235 @@
/*
* p11_cert.c - Handle certificates residing on a PKCS11 token
*
* Copyright (C) 2002, Olaf Kirch <okir@lst.de>
*/
#include "pkcs11-internal.h"
static int pkcs11_find_certs(PKCS11_TOKEN *);
static int pkcs11_next_cert(PKCS11_CTX *, PKCS11_TOKEN *,
CK_SESSION_HANDLE);
static int pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
PKCS11_CERT **);
static int pkcs11_store_certificate(PKCS11_TOKEN *, X509 *,
char *, unsigned char *, unsigned int,
PKCS11_CERT **);
static CK_OBJECT_CLASS cert_search_class;
static CK_ATTRIBUTE cert_search_attrs[] = {
{ CKA_CLASS, &cert_search_class, sizeof(cert_search_class) },
};
#define numof(arr) (sizeof(arr)/sizeof((arr)[0]))
/*
* Enumerate all certs on the card
*/
int
PKCS11_enumerate_certs(PKCS11_TOKEN *token,
PKCS11_CERT **certp,
unsigned int *countp)
{
PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
if (priv->ncerts < 0) {
priv->ncerts = 0;
if (pkcs11_find_certs(token)) {
pkcs11_destroy_certs(token);
return -1;
}
}
*certp = priv->certs;
*countp = priv->ncerts;
return 0;
}
/*
* Find certificate matching a key
*/
PKCS11_CERT *
PKCS11_find_certificate(PKCS11_KEY *key)
{
PKCS11_KEY_private *kpriv;
PKCS11_CERT_private *cpriv;
PKCS11_CERT *cert;
unsigned int n, count;
kpriv = PRIVKEY(key);
if (PKCS11_enumerate_certs(KEY2TOKEN(key), &cert, &count))
return NULL;
for (n = 0; n < count; n++, cert++) {
cpriv = PRIVCERT(cert);
if (cpriv->id_len == kpriv->id_len
&& !memcmp(cpriv->id, kpriv->id, kpriv->id_len))
return cert;
}
return NULL;
}
/*
* Find all certs of a given type (public or private)
*/
int
pkcs11_find_certs(PKCS11_TOKEN *token)
{
PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
CK_SESSION_HANDLE session;
int rv, res = -1;
/* Make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 0))
return -1;
session = PRIVSLOT(slot)->session;
/* Tell the PKCS11 lib to enumerate all matching objects */
cert_search_class = CKO_CERTIFICATE;
rv = CRYPTOKI_call(ctx, C_FindObjectsInit(session, cert_search_attrs,
numof(cert_search_attrs)));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv);
do {
res = pkcs11_next_cert(ctx, token, session);
} while (res == 0);
CRYPTOKI_call(ctx, C_FindObjectsFinal(session));
return (res < 0)? -1 : 0;
}
int
pkcs11_next_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session)
{
CK_OBJECT_HANDLE obj;
CK_ULONG count;
int rv;
/* Get the next matching object */
rv = CRYPTOKI_call(ctx, C_FindObjects(session, &obj, 1, &count));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv);
if (count == 0)
return 1;
if (pkcs11_init_cert(ctx, token, session, obj, NULL))
return -1;
return 0;
}
int
pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj,
PKCS11_CERT **ret)
{
PKCS11_TOKEN_private *tpriv;
PKCS11_CERT_private *kpriv;
PKCS11_CERT *cert;
char label[256], data[2048];
CK_CERTIFICATE_TYPE cert_type;
size_t size;
size = sizeof(cert_type);
if (pkcs11_getattr_var(token, obj, CKA_CERTIFICATE_TYPE,
&cert_type, &size))
return -1;
/* Ignore any certs we don't understand */
if (cert_type != CKC_X_509)
return 0;
tpriv = PRIVTOKEN(token);
tpriv->certs = (PKCS11_CERT *) OPENSSL_realloc(tpriv->certs,
(tpriv->ncerts + 1) * sizeof(PKCS11_CERT));
cert = tpriv->certs + tpriv->ncerts++;
memset(cert, 0, sizeof(*cert));
cert->_private = kpriv = PKCS11_NEW(PKCS11_CERT_private);
kpriv->object = obj;
kpriv->parent = token;
if (!pkcs11_getattr_s(token, obj, CKA_LABEL, label, sizeof(label)))
cert->label = BUF_strdup(label);
size = sizeof(data);
if (!pkcs11_getattr_var(token, obj, CKA_VALUE, data, &size)) {
unsigned char *p = data;
cert->x509 = d2i_X509(NULL, &p, size);
}
/* Initialize internal information */
kpriv->id_len = sizeof(kpriv->id);
if (pkcs11_getattr_var(token, obj, CKA_ID, kpriv->id, &kpriv->id_len))
kpriv->id_len = 0;
if (ret)
*ret = cert;
return 0;
}
/*
* Destroy all certs
*/
void
pkcs11_destroy_certs(PKCS11_TOKEN *token)
{
PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
while (priv->ncerts > 0) {
PKCS11_CERT *cert = &priv->certs[--(priv->ncerts)];
if (cert->x509)
X509_free(cert->x509);
OPENSSL_free(cert->label);
}
if (priv->certs)
OPENSSL_free(priv->certs);
priv->ncerts = -1;
priv->certs = NULL;
}
/*
* Store certificate
*/
int
pkcs11_store_certificate(PKCS11_TOKEN *token, X509 *x509, char *label,
unsigned char *id, unsigned int id_len,
PKCS11_CERT **ret_cert)
{
PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE object;
CK_ATTRIBUTE attrs[32];
unsigned int n = 0;
int rv;
/* First, make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
return -1;
session = PRIVSLOT(slot)->session;
/* Now build the template */
pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_CERTIFICATE);
pkcs11_addattr_int(attrs + n++, CKA_CERTIFICATE_TYPE, CKC_X_509);
pkcs11_addattr_obj(attrs + n++, CKA_VALUE,
(pkcs11_i2d_fn) i2d_X509, x509);
if (label)
pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
if (id && id_len)
pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);
/* Now call the pkcs11 module to create the object */
rv = CRYPTOKI_call(ctx, C_CreateObject(session, attrs, n, &object));
/* Zap all memory allocated when building the template */
pkcs11_zap_attrs(attrs, n);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_CERTIFICATE, rv);
/* Gobble the key object */
return pkcs11_init_cert(ctx, token, session,
object, ret_cert);
}

208
src/sslengines/p11_err.c Normal file
View File

@ -0,0 +1,208 @@
/* p11_err.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#include "pkcs11-internal.h"
/* BEGIN ERROR CODES */
#ifndef NO_ERR
static ERR_STRING_DATA PKCS11_str_library[] = {
{ERR_PACK(ERR_LIB_PKCS11,0,0) ,"PKCS11 library"},
{0, NULL}
};
static ERR_STRING_DATA PKCS11_str_functs[] = {
{ERR_PACK(0, PKCS11_F_PKCS11_CTX_LOAD, 0), "PKCS11_CTX_load" },
{ERR_PACK(0, PKCS11_F_PKCS11_ENUM_SLOTS, 0), "PKCS11_enum_slots" },
{ERR_PACK(0, PKCS11_F_PKCS11_CHECK_TOKEN, 0), "PKCS11_check_token" },
{ERR_PACK(0, PKCS11_F_PKCS11_OPEN_SESSION, 0), "PKCS11_open_session" },
{ERR_PACK(0, PKCS11_F_PKCS11_LOGIN, 0), "PKCS11_login" },
{ERR_PACK(0, PKCS11_F_PKCS11_ENUM_KEYS, 0), "PKCS11_enum_keys" },
{ERR_PACK(0, PKCS11_F_PKCS11_GET_KEY, 0), "PKCS11_get_key" },
{ERR_PACK(0, PKCS11_F_PKCS11_RSA_DECRYPT, 0), "PKCS11_rsa_decrypt" },
{ERR_PACK(0, PKCS11_F_PKCS11_RSA_ENCRYPT, 0), "PKCS11_rsa_encrypt" },
{ERR_PACK(0, PKCS11_F_PKCS11_RSA_SIGN, 0), "PKCS11_rsa_sign" },
{ERR_PACK(0, PKCS11_F_PKCS11_RSA_VERIFY, 0), "PKCS11_rsa_verify" },
{ERR_PACK(0, PKCS11_F_PKCS11_ENUM_CERTS, 0), "PKCS11_enum_certs" },
{ERR_PACK(0, PKCS11_F_PKCS11_INIT_TOKEN, 0), "PKCS11_init_token" },
{ERR_PACK(0, PKCS11_F_PKCS11_INIT_PIN, 0), "PKCS11_init_pin" },
{ERR_PACK(0, PKCS11_F_PKCS11_GETATTR, 0), "PKCS11_get_attribute" },
{ERR_PACK(0, PKCS11_F_PKCS11_LOGOUT, 0), "PKCS11_logout" },
{ERR_PACK(0, PKCS11_F_PKCS11_STORE_PRIVATE_KEY, 0),"PKCS11_store_private_key" },
{ERR_PACK(0, PKCS11_F_PKCS11_GENERATE_KEY, 0), "PKCS11_generate_key" },
{ERR_PACK(0, PKCS11_F_PKCS11_STORE_PUBLIC_KEY, 0),"PKCS11_store_public_key" },
{ERR_PACK(0, PKCS11_F_PKCS11_STORE_CERTIFICATE, 0),"PKCS11_store_certificate" },
{0, NULL}
};
static ERR_STRING_DATA PKCS11_str_reasons[] = {
{PKCS11_LOAD_MODULE_ERROR ,"Unable to load PKCS#11 module" },
{PKCS11_MODULE_LOADED_ERROR ,"Already loaded module for PKCS11 context" },
{PKCS11_SYMBOL_NOT_FOUND_ERROR ,"Symbol not found in PKCS#11 module" },
{PKCS11_NOT_SUPPORTED ,"Not supported" },
{PKCS11_NO_SESSION ,"No session open" },
{CKR_CANCEL, "Cancel" },
{CKR_HOST_MEMORY, "Host memory error" },
{CKR_SLOT_ID_INVALID, "Invalid slot ID" },
{CKR_GENERAL_ERROR, "General Error" },
{CKR_FUNCTION_FAILED, "Function failed" },
{CKR_ARGUMENTS_BAD, "Invalid arguments" },
{CKR_NO_EVENT, "No event" },
{CKR_NEED_TO_CREATE_THREADS, "Need to create threads" },
{CKR_CANT_LOCK, "Cannott lock" },
{CKR_ATTRIBUTE_READ_ONLY, "Attribute read only" },
{CKR_ATTRIBUTE_SENSITIVE, "Attribute sensitive" },
{CKR_ATTRIBUTE_TYPE_INVALID, "Attribute type invalid" },
{CKR_ATTRIBUTE_VALUE_INVALID, "Attribute value invalid" },
{CKR_DATA_INVALID, "Data invalid" },
{CKR_DATA_LEN_RANGE, "Data len range" },
{CKR_DEVICE_ERROR, "Device error" },
{CKR_DEVICE_MEMORY, "Device memory" },
{CKR_DEVICE_REMOVED, "Device removed" },
{CKR_ENCRYPTED_DATA_INVALID, "Encrypted data invalid" },
{CKR_ENCRYPTED_DATA_LEN_RANGE, "Encrypted data len range" },
{CKR_FUNCTION_CANCELED, "Function canceled" },
{CKR_FUNCTION_NOT_PARALLEL, "Function not parallel" },
{CKR_FUNCTION_NOT_SUPPORTED, "Function not supported" },
{CKR_KEY_HANDLE_INVALID, "Key handle invalid" },
{CKR_KEY_SIZE_RANGE, "Key size range" },
{CKR_KEY_TYPE_INCONSISTENT, "Key type inconsistent" },
{CKR_KEY_NOT_NEEDED, "Key not needed" },
{CKR_KEY_CHANGED, "Key changed" },
{CKR_KEY_NEEDED, "Key needed" },
{CKR_KEY_INDIGESTIBLE, "Key indigestible" },
{CKR_KEY_FUNCTION_NOT_PERMITTED,"Key function not permitted" },
{CKR_KEY_NOT_WRAPPABLE, "Key not wrappable" },
{CKR_KEY_UNEXTRACTABLE, "Key unextractable" },
{CKR_MECHANISM_INVALID, "Mechanism invalid" },
{CKR_MECHANISM_PARAM_INVALID, "Mechanism param invalid" },
{CKR_OBJECT_HANDLE_INVALID, "Object handle invalid" },
{CKR_OPERATION_ACTIVE, "Operation active" },
{CKR_OPERATION_NOT_INITIALIZED, "Operation not initialized" },
{CKR_PIN_INCORRECT, "PIN incorrect" },
{CKR_PIN_INVALID, "PIN invalid" },
{CKR_PIN_LEN_RANGE, "Invalid PIN length" },
{CKR_PIN_EXPIRED, "PIN expired" },
{CKR_PIN_LOCKED, "PIN locked" },
{CKR_SESSION_CLOSED, "Session closed" },
{CKR_SESSION_COUNT, "Session count" },
{CKR_SESSION_HANDLE_INVALID, "Session handle invalid" },
{CKR_SESSION_PARALLEL_NOT_SUPPORTED,
"Session parallel not supported" },
{CKR_SESSION_READ_ONLY, "Session read only" },
{CKR_SESSION_EXISTS, "Session exists" },
{CKR_SESSION_READ_ONLY_EXISTS, "Read-only session exists" },
{CKR_SESSION_READ_WRITE_SO_EXISTS,
"Read/write SO session exists" },
{CKR_SIGNATURE_INVALID, "Signature invalid" },
{CKR_SIGNATURE_LEN_RANGE, "Signature len range" },
{CKR_TEMPLATE_INCOMPLETE, "Incomplete template" },
{CKR_TEMPLATE_INCONSISTENT, "Inconsistent template" },
{CKR_TOKEN_NOT_PRESENT, "No PKCS#11 token present" },
{CKR_TOKEN_NOT_RECOGNIZED, "PKCS#11 token not recognized" },
{CKR_TOKEN_WRITE_PROTECTED, "Token write protected" },
{CKR_UNWRAPPING_KEY_HANDLE_INVALID,
"Unwrapping key handle invalid" },
{CKR_UNWRAPPING_KEY_SIZE_RANGE, "Unwrapping key size range" },
{CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
"Unwrapping key type inconsistent" },
{CKR_USER_ALREADY_LOGGED_IN, "User already logged in" },
{CKR_USER_NOT_LOGGED_IN, "User not logged in" },
{CKR_USER_PIN_NOT_INITIALIZED, "User pin not initialized" },
{CKR_USER_TYPE_INVALID, "User type invalid" },
{CKR_USER_ANOTHER_ALREADY_LOGGED_IN,
"User another is already logged in" },
{CKR_USER_TOO_MANY_TYPES, "User too many types" },
{CKR_WRAPPED_KEY_INVALID, "Wrapped key invalid" },
{CKR_WRAPPED_KEY_LEN_RANGE, "Wrapped key len range" },
{CKR_WRAPPING_KEY_HANDLE_INVALID,
"Wrapping key handle invalid" },
{CKR_WRAPPING_KEY_SIZE_RANGE, "Wrapping key size range" },
{CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
"Wrapping key type inconsistent" },
{CKR_RANDOM_SEED_NOT_SUPPORTED, "Random seed not supported" },
{CKR_RANDOM_NO_RNG, "Random no rng" },
{CKR_DOMAIN_PARAMS_INVALID, "Domain params invalid" },
{CKR_BUFFER_TOO_SMALL, "Buffer too small" },
{CKR_SAVED_STATE_INVALID, "Saved state invalid" },
{CKR_INFORMATION_SENSITIVE, "Information sensitive" },
{CKR_STATE_UNSAVEABLE, "State unsaveable" },
{CKR_CRYPTOKI_NOT_INITIALIZED, "Cryptoki not initialized" },
{CKR_CRYPTOKI_ALREADY_INITIALIZED,
"Cryptoki already initialized" },
{CKR_MUTEX_BAD, "Mutex bad" },
{CKR_MUTEX_NOT_LOCKED, "Mutex not locked" },
{CKR_VENDOR_DEFINED, "Vendor defined" },
{0, NULL}
};
#endif
void
ERR_load_PKCS11_strings(void)
{
static int init = 1;
if (init) {
init = 0;
#ifndef NO_ERR
ERR_load_strings(0, PKCS11_str_library);
ERR_load_strings(ERR_LIB_PKCS11, PKCS11_str_functs);
ERR_load_strings(ERR_LIB_PKCS11, PKCS11_str_reasons);
#endif
}
}

425
src/sslengines/p11_key.c Normal file
View File

@ -0,0 +1,425 @@
/* p11_key.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#include "pkcs11-internal.h"
static int pkcs11_find_keys(PKCS11_TOKEN *, unsigned int);
static int pkcs11_next_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_CLASS type);
static int pkcs11_init_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
CK_OBJECT_CLASS type, PKCS11_KEY **);
static int pkcs11_store_private_key(PKCS11_TOKEN *, EVP_PKEY *, char *,
unsigned char *, unsigned int,
PKCS11_KEY **);
static int pkcs11_store_public_key(PKCS11_TOKEN *, EVP_PKEY *, char *,
unsigned char *, unsigned int,
PKCS11_KEY **);
static CK_OBJECT_CLASS key_search_class;
static CK_ATTRIBUTE key_search_attrs[] = {
{ CKA_CLASS, &key_search_class, sizeof(key_search_class) },
};
#define numof(arr) (sizeof(arr)/sizeof((arr)[0]))
/*
* Enumerate all keys on the card
* For now, we enumerate just the private keys.
*/
int
PKCS11_enumerate_keys(PKCS11_TOKEN *token,
PKCS11_KEY **keyp,
unsigned int *countp)
{
PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
if (priv->nkeys < 0) {
priv->nkeys = 0;
if (pkcs11_find_keys(token, CKO_PRIVATE_KEY)) {
pkcs11_destroy_keys(token);
return -1;
}
priv->nprkeys = priv->nkeys;
if (pkcs11_find_keys(token, CKO_PUBLIC_KEY)) {
pkcs11_destroy_keys(token);
return -1;
}
}
*keyp = priv->keys;
*countp = priv->nprkeys;
return 0;
}
/*
* Store a private key on the token
*/
int
PKCS11_store_private_key(PKCS11_TOKEN *token, EVP_PKEY *pk, char *label)
{
if (pkcs11_store_private_key(token, pk, label, NULL, 0, NULL))
return -1;
return 0;
}
/*
* Generate and store a private key on the token
* FIXME: We should check first whether the token supports
* on-board key generation, and if it does, use its own algorithm
*/
int
PKCS11_generate_key(PKCS11_TOKEN *token,
int algorithm, unsigned int bits,
char *label)
{
PKCS11_KEY *key_obj;
EVP_PKEY *pk;
RSA *rsa;
BIO *err;
int rc;
if (algorithm != EVP_PKEY_RSA) {
PKCS11err(PKCS11_F_PKCS11_GENERATE_KEY,
PKCS11_NOT_SUPPORTED);
return -1;
}
err = BIO_new_fp(stderr, BIO_NOCLOSE);
rsa = RSA_generate_key(bits, 0x10001, NULL, err);
BIO_free(err);
if (rsa == NULL) {
PKCS11err(PKCS11_F_PKCS11_GENERATE_KEY,
PKCS11_KEYGEN_FAILED);
return -1;
}
pk = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pk, rsa);
rc = pkcs11_store_private_key(token, pk, label, NULL, 0, &key_obj);
if (rc == 0) {
PKCS11_KEY_private *kpriv;
kpriv = PRIVKEY(key_obj);
rc = pkcs11_store_public_key(token, pk, label,
kpriv->id, kpriv->id_len, NULL);
}
EVP_PKEY_free(pk);
return rc;
}
/*
* Get the key type
*/
int
PKCS11_get_key_type(PKCS11_KEY *key)
{
PKCS11_KEY_private *priv = PRIVKEY(key);
return priv->ops->type;
}
/*
* Create a key object that will allow an OpenSSL application
* to use the token via an EVP_PKEY
*/
EVP_PKEY *
PKCS11_get_private_key(PKCS11_KEY *key)
{
PKCS11_KEY_private *priv = PRIVKEY(key);
EVP_PKEY *pk;
pk = EVP_PKEY_new();
if (priv->ops->get_private(key, pk)
|| priv->ops->get_public(key, pk)) {
EVP_PKEY_free(pk);
return NULL;
}
key->evp_key = pk;
return pk;
}
/*
* Find all keys of a given type (public or private)
*/
int
pkcs11_find_keys(PKCS11_TOKEN *token, unsigned int type)
{
PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
CK_SESSION_HANDLE session;
int rv, res = -1;
/* Make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 0))
return -1;
session = PRIVSLOT(slot)->session;
/* Tell the PKCS11 lib to enumerate all matching objects */
key_search_class = type;
rv = CRYPTOKI_call(ctx, C_FindObjectsInit(session, key_search_attrs,
numof(key_search_attrs)));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
do {
res = pkcs11_next_key(ctx, token, session, type);
} while (res == 0);
CRYPTOKI_call(ctx, C_FindObjectsFinal(session));
return (res < 0)? -1 : 0;
}
int
pkcs11_next_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_CLASS type)
{
CK_OBJECT_HANDLE obj;
CK_ULONG count;
int rv;
/* Get the next matching object */
rv = CRYPTOKI_call(ctx, C_FindObjects(session, &obj, 1, &count));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
if (count == 0)
return 1;
if (pkcs11_init_key(ctx, token, session, obj, type, NULL))
return -1;
return 0;
}
int
pkcs11_init_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj,
CK_OBJECT_CLASS type,
PKCS11_KEY **ret)
{
PKCS11_TOKEN_private *tpriv;
PKCS11_KEY_private *kpriv;
PKCS11_KEY *key;
char label[256];
CK_KEY_TYPE key_type;
PKCS11_KEY_ops *ops;
size_t size;
size = sizeof(key_type);
if (pkcs11_getattr_var(token, obj, CKA_KEY_TYPE, &key_type, &size))
return -1;
switch (key_type) {
case CKK_RSA:
ops = &pkcs11_rsa_ops;
break;
default:
/* Ignore any keys we don't understand */
return 0;
}
tpriv = PRIVTOKEN(token);
tpriv->keys = (PKCS11_KEY *) OPENSSL_realloc(tpriv->keys,
(tpriv->nkeys + 1) * sizeof(PKCS11_KEY));
key = tpriv->keys + tpriv->nkeys++;
memset(key, 0, sizeof(*key));
key->_private = kpriv = PKCS11_NEW(PKCS11_KEY_private);
kpriv->object = obj;
kpriv->parent = token;
if (!pkcs11_getattr_s(token, obj, CKA_LABEL, label, sizeof(label)))
key->label = BUF_strdup(label);
key->private = (type == CKO_PRIVATE_KEY);
/* Initialize internal information */
kpriv->id_len = sizeof(kpriv->id);
if (pkcs11_getattr_var(token, obj, CKA_ID, kpriv->id, &kpriv->id_len))
kpriv->id_len = 0;
kpriv->ops = ops;
if (ret)
*ret = key;
return 0;
}
/*
* Destroy all keys
*/
void
pkcs11_destroy_keys(PKCS11_TOKEN *token)
{
PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
while (priv->nkeys > 0) {
PKCS11_KEY *key = &priv->keys[--(priv->nkeys)];
if (key->evp_key)
EVP_PKEY_free(key->evp_key);
OPENSSL_free(key->label);
}
if (priv->keys)
OPENSSL_free(priv->keys);
priv->nprkeys = -1;
priv->nkeys = -1;
priv->keys = NULL;
}
/*
* Store private key
*/
int
pkcs11_store_private_key(PKCS11_TOKEN *token, EVP_PKEY *pk, char *label,
unsigned char *id, unsigned int id_len,
PKCS11_KEY **ret_key)
{
PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE object;
CK_ATTRIBUTE attrs[32];
unsigned int n = 0;
int rv;
/* First, make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
return -1;
session = PRIVSLOT(slot)->session;
/* Now build the key attrs */
if (pk->type == EVP_PKEY_RSA) {
RSA *rsa = EVP_PKEY_get1_RSA(pk);
pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_PRIVATE_KEY);
pkcs11_addattr_int(attrs + n++, CKA_KEY_TYPE, CKK_RSA);
pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa->n);
pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa->e);
pkcs11_addattr_bn(attrs + n++, CKA_PRIVATE_EXPONENT, rsa->d);
pkcs11_addattr_bn(attrs + n++, CKA_PRIME_1, rsa->p);
pkcs11_addattr_bn(attrs + n++, CKA_PRIME_2, rsa->q);
if (label)
pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
if (id && id_len)
pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);
} else {
PKCS11err(PKCS11_F_PKCS11_STORE_PRIVATE_KEY,
PKCS11_NOT_SUPPORTED);
return -1;
}
/* Now call the pkcs11 module to create the object */
rv = CRYPTOKI_call(ctx, C_CreateObject(session, attrs, n, &object));
/* Zap all memory allocated when building the template */
pkcs11_zap_attrs(attrs, n);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_PRIVATE_KEY, rv);
/* Gobble the key object */
return pkcs11_init_key(ctx, token, session, object,
CKO_PRIVATE_KEY, ret_key);
}
/*
* Store public key
*/
int
pkcs11_store_public_key(PKCS11_TOKEN *token, EVP_PKEY *pk, char *label,
unsigned char *id, unsigned int id_len,
PKCS11_KEY **ret_key)
{
PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE object;
CK_ATTRIBUTE attrs[32];
unsigned int n = 0;
int rv;
/* First, make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
return -1;
session = PRIVSLOT(slot)->session;
/* Now build the key attrs */
if (pk->type == EVP_PKEY_RSA) {
RSA *rsa = EVP_PKEY_get1_RSA(pk);
pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_PUBLIC_KEY);
pkcs11_addattr_int(attrs + n++, CKA_KEY_TYPE, CKK_RSA);
pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa->n);
pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa->e);
if (label)
pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
if (id && id_len)
pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);
} else {
PKCS11err(PKCS11_F_PKCS11_STORE_PUBLIC_KEY,
PKCS11_NOT_SUPPORTED);
return -1;
}
/* Now call the pkcs11 module to create the object */
rv = CRYPTOKI_call(ctx, C_CreateObject(session, attrs, n, &object));
/* Zap all memory allocated when building the template */
pkcs11_zap_attrs(attrs, n);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_PUBLIC_KEY, rv);
/* Gobble the key object */
return pkcs11_init_key(ctx, token, session,
object, CKO_PUBLIC_KEY, ret_key);
}

178
src/sslengines/p11_load.c Normal file
View File

@ -0,0 +1,178 @@
/* p11_load.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#include <string.h>
#include "pkcs11-internal.h"
#include "libpkcs11.h"
#ifndef PKCS11_MODULE_DIR
#define PKCS11_MODULE_DIR "/usr/lib/pkcs11"
#endif
/* I don't think the comment below applies...? _KLS */
/* Currently, when we dlclose the pkcs11 module, this will
* also unload all sorts of other libraries, e.g. the pcsc-lite
* library. This library installs an exit handler using atexit.
* So when we return from main(), we end up with an exit handler
* pointing to some area of memory where libpcsc-lite used to be,
* but is not anymore. The typical ``watch me walk over the edge
* of that cliff there'' thing.
*/
#undef DLCLOSE_OKAY
#ifndef DLCLOSE_OKAY
//static const char * the_module = NULL;
static void * the_handler = NULL;
#endif
/*
* Create a new context
*/
PKCS11_CTX *
PKCS11_CTX_new()
{
PKCS11_CTX_private *priv;
PKCS11_CTX *ctx;
/* Load error strings */
ERR_load_PKCS11_strings();
priv = PKCS11_NEW(PKCS11_CTX_private);
ctx = PKCS11_NEW(PKCS11_CTX);
ctx->_private = priv;
/* Mark list of slots as "need to fetch from card" */
priv->nslots = -1;
return ctx;
}
/*
* Load the shared library, and initialize it.
*/
int
PKCS11_CTX_load(PKCS11_CTX *ctx, const char *name)
{
PKCS11_CTX_private *priv = PRIVCTX(ctx);
CK_INFO ck_info;
int rv;
if (priv->libinfo != NULL) {
PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_MODULE_LOADED_ERROR);
return -1;
}
the_handler=C_LoadModule(name, &priv->method );
if (!the_handler) {
PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_LOAD_MODULE_ERROR);
return -1;
}
/*
priv->method = PKCS11_NEW(PKCS11_method);
base = (caddr_t) (priv->method);
for (sym = pkcs11_symbols; sym->name; sym++) {
if (!bind_symbol(priv, sym->name, (void **) (base + sym->offset))) {
PKCS11err(PKCS11_F_PKCS11_CTX_LOAD,
PKCS11_SYMBOL_NOT_FOUND_ERROR);
return -1;
}
}
*/
/* Tell the PKCS11 to initialize itself */
rv = priv->method->C_Initialize(NULL);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv);
/* Get info on the library */
rv = priv->method->C_GetInfo(&ck_info);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv);
ctx->manufacturer = PKCS11_DUP(ck_info.manufacturerID);
ctx->description = PKCS11_DUP(ck_info.libraryDescription);
return 0;
}
/*
* Unload the shared library
*/
void
PKCS11_CTX_unload(PKCS11_CTX *ctx)
{
PKCS11_CTX_private *priv;
priv= PRIVCTX(ctx);
/* Free any slot info we have allocated */
pkcs11_destroy_all_slots(ctx);
/* Tell the PKCS11 library to shut down */
priv->method->C_Finalize(NULL);
/* Unload the module */
C_UnloadModule(the_handler);
}
/*
* Free a context
*/
void
PKCS11_CTX_free(PKCS11_CTX *ctx)
{
PKCS11_CTX_unload(ctx); /* Make sure */
OPENSSL_free(ctx->manufacturer);
OPENSSL_free(ctx->description);
OPENSSL_free(ctx->_private);
OPENSSL_free(ctx);
}

97
src/sslengines/p11_misc.c Normal file
View File

@ -0,0 +1,97 @@
/* p11_misc.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#include <openssl/crypto.h>
#include "pkcs11-internal.h"
void *
pkcs11_malloc(size_t size)
{
void *p = OPENSSL_malloc(size);
memset(p, 0, size);
return p;
}
/* PKCS11 strings are fixed size blank padded,
* so when strduping them we must make sure
* we stop at the end of the buffer, and while we're
* at it it's nice to remove the padding */
char *
pkcs11_strdup(char *mem, size_t size)
{
char *res;
while (size && mem[size-1] == ' ')
size--;
res = OPENSSL_malloc(size+1);
memcpy(res, mem, size);
res[size] = '\0';
return res;
}
/*
* Dup memory
*/
void *
memdup(const void *src, size_t size)
{
void *dst;
dst = malloc(size);
memcpy(dst, src, size);
return dst;
}

235
src/sslengines/p11_rsa.c Normal file
View File

@ -0,0 +1,235 @@
/* p11_rsa.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
/*
* This file implements the handling of RSA keys stored on a
* PKCS11 token
*/
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include "pkcs11-internal.h"
static int pkcs11_get_rsa_public(PKCS11_KEY *, EVP_PKEY *);
static int pkcs11_get_rsa_private(PKCS11_KEY *, EVP_PKEY *);
RSA_METHOD * pkcs11_get_rsa_method();
#define key_getattr(k, t, p, s) \
pkcs11_getattr(KEY2TOKEN(key), PRIVKEY(key)->object, t, p, s)
#define key_getattr_bn(k, t, bn) \
pkcs11_getattr_bn(KEY2TOKEN(key), PRIVKEY(key)->object, t, bn)
/*
* Get RSA key material
*/
int
pkcs11_get_rsa_private(PKCS11_KEY *key, EVP_PKEY *pk)
{
CK_BBOOL sensitive, extractable;
RSA *rsa;
if (!(rsa = EVP_PKEY_get1_RSA(pk))) {
ERR_clear_error(); /* the above flags an error */
rsa = RSA_new();
EVP_PKEY_set1_RSA(pk, rsa);
}
if (key_getattr(key, CKA_SENSITIVE, &sensitive, sizeof(sensitive))
|| key_getattr(key, CKA_EXTRACTABLE, &extractable, sizeof(extractable)))
return -1;
if (!rsa->n && key_getattr_bn(key, CKA_MODULUS, &rsa->n))
return -1;
if (!rsa->e && key_getattr_bn(key, CKA_PUBLIC_EXPONENT, &rsa->e))
return -1;
/* If the key is not extractable, create a key object
* that will use the card's functions to sign & decrypt */
if (sensitive || !extractable) {
RSA_set_method(rsa, pkcs11_get_rsa_method());
rsa->flags |= RSA_FLAG_SIGN_VER;
RSA_set_app_data(rsa, key);
return 0;
}
/* TBD - extract RSA private key. */
PKCS11err(PKCS11_F_PKCS11_GET_KEY, PKCS11_NOT_SUPPORTED);
return -1;
}
int
pkcs11_get_rsa_public(PKCS11_KEY *key, EVP_PKEY *pk)
{
/* TBD */
return 0;
}
static int
pkcs11_rsa_decrypt(int flen, const u_char *from, u_char *to,
RSA *rsa, int padding)
{
PKCS11_KEY *key = (PKCS11_KEY *) RSA_get_app_data(rsa);
if (padding != RSA_PKCS1_PADDING)
return -1;
if (key == NULL)
return -1;
/* PKCS11 calls go here */
PKCS11err(PKCS11_F_PKCS11_RSA_DECRYPT, PKCS11_NOT_SUPPORTED);
return -1;
}
static int
pkcs11_rsa_encrypt(int flen, const u_char *from, u_char *to,
RSA *rsa, int padding)
{
/* PKCS11 calls go here */
PKCS11err(PKCS11_F_PKCS11_RSA_ENCRYPT, PKCS11_NOT_SUPPORTED);
return -1;
}
static int
pkcs11_rsa_sign(int type, const u_char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
{
PKCS11_KEY *key = (PKCS11_KEY *) RSA_get_app_data(rsa);
PKCS11_KEY_private *priv;
PKCS11_SLOT *slot;
PKCS11_CTX *ctx;
CK_SESSION_HANDLE session;
CK_MECHANISM mechanism;
CK_ULONG sigsize;
int rv;
if (key == NULL)
return -1;
ctx = KEY2CTX(key);
priv = PRIVKEY(key);
slot = TOKEN2SLOT(priv->parent);
session = PRIVSLOT(slot)->session;
memset(&mechanism, 0, sizeof(mechanism));
mechanism.mechanism = CKM_RSA_PKCS;
rv = CRYPTOKI_call(ctx, C_SignInit(session, &mechanism, priv->object));
if (rv)
goto fail;
/* API is somewhat fishy here. *siglen is 0 on entry (cleared
* by OpenSSL). The library assumes that the memory passed
* by the caller is always big enough */
sigsize = BN_num_bytes(rsa->n);
rv = CRYPTOKI_call(ctx, C_Sign(session, m, m_len, sigret, &sigsize));
if (rv)
goto fail;
*siglen = sigsize;
return 1;
fail: PKCS11err(PKCS11_F_PKCS11_RSA_SIGN, pkcs11_map_err(rv));
return 0;
}
/* Lousy hack alert. If RSA_verify detects that the key has the
* RSA_FLAG_SIGN_VER flags set, it will assume that verification
* is implemented externally as well.
* We work around this by temporarily cleaning the flag, and
* calling RSA_verify once more.
*/
static int
pkcs11_rsa_verify(int type, const u_char *m, unsigned int m_len,
unsigned char *signature, unsigned int siglen, const RSA *rsa)
{
int res;
if (rsa->flags & RSA_FLAG_SIGN_VER) {
rsa->flags &= ~RSA_FLAG_SIGN_VER;
res = RSA_verify(type, m, m_len, signature, siglen, rsa);
rsa->flags |= RSA_FLAG_SIGN_VER;
} else {
PKCS11err(PKCS11_F_PKCS11_RSA_VERIFY, PKCS11_NOT_SUPPORTED);
res = 0;
}
return res;
}
/*
* Overload the default OpenSSL methods for RSA
*/
RSA_METHOD *
pkcs11_get_rsa_method()
{
static RSA_METHOD ops;
if (!ops.rsa_priv_enc) {
ops = *RSA_get_default_method();
ops.rsa_priv_enc = pkcs11_rsa_encrypt;
ops.rsa_priv_dec = pkcs11_rsa_decrypt;
ops.rsa_sign = pkcs11_rsa_sign;
ops.rsa_verify = pkcs11_rsa_verify;
}
return &ops;
}
PKCS11_KEY_ops pkcs11_rsa_ops = {
EVP_PKEY_RSA,
pkcs11_get_rsa_public,
pkcs11_get_rsa_private
};

366
src/sslengines/p11_slot.c Normal file
View File

@ -0,0 +1,366 @@
/* p11_slot.c */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#include <openssl/buffer.h>
#include "pkcs11-internal.h"
static int pkcs11_init_slot(PKCS11_CTX *, PKCS11_SLOT *, CK_SLOT_ID);
static int pkcs11_check_token(PKCS11_CTX *, PKCS11_SLOT *);
static void pkcs11_destroy_token(PKCS11_TOKEN *);
/*
* Enumerate slots
*/
int
PKCS11_enumerate_slots(PKCS11_CTX *ctx,
PKCS11_SLOT **slotp,
unsigned int *countp)
{
PKCS11_CTX_private *priv = PRIVCTX(ctx);
if (priv->nslots < 0) {
CK_ULONG nslots, n;
CK_SLOT_ID slotid[64];
PKCS11_SLOT *slots;
int rv;
rv = priv->method->C_GetSlotList(FALSE, slotid, &nslots);
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);
slots = (PKCS11_SLOT *) pkcs11_malloc(nslots
* sizeof(PKCS11_SLOT));
for (n = 0; n < nslots; n++) {
if (pkcs11_init_slot(ctx, &slots[n], slotid[n])) {
while (n--)
pkcs11_destroy_slot(ctx, slots + n);
OPENSSL_free(slots);
return -1;
}
}
priv->nslots = nslots;
priv->slots = slots;
}
*slotp = priv->slots;
*countp = priv->nslots;
return 0;
}
/*
* Find a slot with a token that looks "valuable"
*/
PKCS11_SLOT *
PKCS11_find_token(PKCS11_CTX *ctx)
{
PKCS11_SLOT *slot_list, *slot, *best;
PKCS11_TOKEN *tok;
unsigned int n, nslots;
if (PKCS11_enumerate_slots(ctx, &slot_list, &nslots))
return NULL;
best = NULL;
for (n = 0, slot = slot_list; n < nslots; n++, slot++) {
if ((tok = slot->token) != NULL) {
if (best == NULL
|| (tok->initialized > best->token->initialized
&& tok->userPinSet > best->token->userPinSet
&& tok->loginRequired > best->token->loginRequired))
best = slot;
}
}
return best;
}
/*
* Open a session with this slot
*/
int
PKCS11_open_session(PKCS11_SLOT *slot, int rw)
{
PKCS11_SLOT_private *priv = PRIVSLOT(slot);
PKCS11_CTX *ctx = SLOT2CTX(slot);
int rv;
if (priv->haveSession) {
CRYPTOKI_call(ctx, C_CloseSession(priv->session));
priv->haveSession = 0;
}
rv = CRYPTOKI_call(ctx,
C_OpenSession(priv->id,
CKF_SERIAL_SESSION | (rw? CKF_RW_SESSION : 0),
NULL, NULL, &priv->session));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_OPEN_SESSION, rv);
priv->haveSession = 1;
return 0;
}
/*
* Authenticate with the card
*/
int
PKCS11_login(PKCS11_SLOT *slot, int so, char *pin)
{
PKCS11_SLOT_private *priv = PRIVSLOT(slot);
PKCS11_CTX *ctx = priv->parent;
int rv;
/* Calling PKCS11_login invalidates all cached
* keys we have */
if (slot->token)
pkcs11_destroy_keys(slot->token);
if (priv->loggedIn) {
/* already logged in, log out first */
if (PKCS11_logout(slot))
return -1;
}
if (!priv->haveSession) {
/* SO gets a r/w session by default,
* user gets a r/o session by default. */
if (PKCS11_open_session(slot, so))
return -1;
}
rv = CRYPTOKI_call(ctx, C_Login(priv->session,
so? CKU_SO : CKU_USER,
pin, strlen(pin)));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGIN, rv);
priv->loggedIn = 1;
return 0;
}
/*
* Log out
*/
int
PKCS11_logout(PKCS11_SLOT *slot)
{
PKCS11_SLOT_private *priv = PRIVSLOT(slot);
PKCS11_CTX *ctx = priv->parent;
int rv;
/* Calling PKCS11_logout invalidates all cached
* keys we have */
if (slot->token)
pkcs11_destroy_keys(slot->token);
if (!priv->haveSession) {
PKCS11err(PKCS11_F_PKCS11_LOGOUT, PKCS11_NO_SESSION);
return -1;
}
rv = CRYPTOKI_call(ctx, C_Logout(priv->session));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGOUT, rv);
priv->loggedIn = 0;
return 0;
}
/*
* Initialize the token
*/
int
PKCS11_init_token(PKCS11_TOKEN *token, char *pin, char *label)
{
PKCS11_SLOT_private *priv = PRIVSLOT(TOKEN2SLOT(token));
PKCS11_CTX_private *cpriv;
PKCS11_CTX *ctx = priv->parent;
int n, rv;
if (!label)
label = "PKCS#11 Token";
rv = CRYPTOKI_call(ctx, C_InitToken(priv->id,
pin, strlen(pin), label));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_INIT_TOKEN, rv);
cpriv = PRIVCTX(ctx);
for (n = 0; n < cpriv->nslots; n++) {
if (pkcs11_check_token(ctx, cpriv->slots + n) < 0)
return -1;
}
return 0;
}
/*
* Set the User PIN
*/
int
PKCS11_init_pin(PKCS11_TOKEN *token, char *pin)
{
PKCS11_SLOT_private *priv = PRIVSLOT(TOKEN2SLOT(token));
PKCS11_CTX *ctx = priv->parent;
int len, rv;
if (!priv->haveSession) {
PKCS11err(PKCS11_F_PKCS11_INIT_PIN, PKCS11_NO_SESSION);
return -1;
}
len = pin? strlen(pin) : 0;
rv = CRYPTOKI_call(ctx, C_InitPIN(priv->session, pin, len));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_INIT_PIN, rv);
return pkcs11_check_token(ctx, TOKEN2SLOT(token));
}
/*
* Helper functions
*/
int
pkcs11_init_slot(PKCS11_CTX *ctx, PKCS11_SLOT *slot, CK_SLOT_ID id)
{
PKCS11_SLOT_private *priv;
CK_SLOT_INFO info;
int rv;
rv = CRYPTOKI_call(ctx, C_GetSlotInfo(id, &info));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);
priv = PKCS11_NEW(PKCS11_SLOT_private);
priv->parent = ctx;
priv->id = id;
slot->description = PKCS11_DUP(info.slotDescription);
slot->manufacturer = PKCS11_DUP(info.manufacturerID);
slot->removable = (info.flags & CKF_REMOVABLE_DEVICE)? 1 : 0;
slot->_private = priv;
if ((info.flags & CKF_TOKEN_PRESENT) && pkcs11_check_token(ctx, slot))
return -1;
return 0;
}
void
pkcs11_destroy_all_slots(PKCS11_CTX *ctx)
{
PKCS11_CTX_private *priv = PRIVCTX(ctx);
while (priv->nslots > 0)
pkcs11_destroy_slot(ctx, &priv->slots[--(priv->nslots)]);
OPENSSL_free(priv->slots);
priv->slots = NULL;
priv->nslots = -1;
}
void
pkcs11_destroy_slot(PKCS11_CTX *ctx, PKCS11_SLOT *slot)
{
PKCS11_SLOT_private *priv = PRIVSLOT(slot);
CRYPTOKI_call(ctx, C_CloseAllSessions(priv->id));
OPENSSL_free(slot->_private);
OPENSSL_free(slot->description);
OPENSSL_free(slot->manufacturer);
if (slot->token) {
pkcs11_destroy_token(slot->token);
OPENSSL_free(slot->token);
}
memset(slot, 0, sizeof(*slot));
}
int
pkcs11_check_token(PKCS11_CTX *ctx, PKCS11_SLOT *slot)
{
PKCS11_SLOT_private *priv = PRIVSLOT(slot);
PKCS11_TOKEN_private *tpriv;
CK_TOKEN_INFO info;
PKCS11_TOKEN *token;
int rv;
if (slot->token)
pkcs11_destroy_token(slot->token);
else
slot->token = PKCS11_NEW(PKCS11_TOKEN);
token = slot->token;
rv = CRYPTOKI_call(ctx, C_GetTokenInfo(priv->id, &info));
if (rv == CKR_TOKEN_NOT_PRESENT) {
OPENSSL_free(token);
slot->token = NULL;
return 0;
}
CRYPTOKI_checkerr(PKCS11_F_PKCS11_CHECK_TOKEN, rv);
/* We have a token */
tpriv = PKCS11_NEW(PKCS11_TOKEN_private);
tpriv->parent = slot;
tpriv->nkeys = -1;
tpriv->ncerts = -1;
token->label = PKCS11_DUP(info.label);
token->manufacturer = PKCS11_DUP(info.manufacturerID);
token->model = PKCS11_DUP(info. model);
token->initialized = (info.flags & CKF_TOKEN_INITIALIZED)? 1 : 0;
token->loginRequired = (info.flags & CKF_LOGIN_REQUIRED)? 1 : 0;
token->userPinSet = (info.flags & CKF_USER_PIN_INITIALIZED)? 1 : 0;
token->readOnly = (info.flags & CKF_WRITE_PROTECTED)? 1 : 0;
token->_private = tpriv;
return 0;
}
void
pkcs11_destroy_token(PKCS11_TOKEN *token)
{
/* XXX destroy keys associated with this token */
OPENSSL_free(token->label);
OPENSSL_free(token->manufacturer);
OPENSSL_free(token->model);
OPENSSL_free(token->_private);
memset(token, 0, sizeof(*token));
}

View File

@ -0,0 +1,358 @@
/* pkcs11.h */
/* Written by Olaf Kirch <okir@lst.de>
*/
/* ====================================================================
* Copyright (c) 1999 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
* the documentation and/or other materials provided with the
* 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).
*
*/
#ifndef HEADER_PKCS11_INTERNAL_H
#define HEADER_PKCS11_INTERNAL_H
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#ifdef __cplusplus
extern "C" {
#endif
/* PKCS11 specific weirdo macros */
#define CK_PTR *
#define NULL_PTR 0
#define CK_DEFINE_FUNCTION(returnType, name) \
returnType name
#define CK_DECLARE_FUNCTION(returnType, name) \
returnType name
#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
returnType (*name)
#define CK_CALLBACK_FUNCTION(returnType, name) \
returnType (*name)
#include "opensc/rsaref/pkcs11.h"
/* get some structures for local code to handle pkcs11 data readily */
/* Use the first free lib ID available */
#define ERR_LIB_PKCS11 42
#define PKCS11err(f,r) \
ERR_PUT_error(ERR_LIB_PKCS11,(f),(r),__FILE__,__LINE__)
/*
* The purpose of this library is to provide a simple PKCS11
* interface to OpenSSL application that wish to use a previously
* initialized card (as opposed to initializing it, etc).
*
* I am therefore making some simplifying assumptions:
*
* - no support for any operations that alter the card,
* i.e. readonly-login
*
* Rather than include the complete PKCS#11 type definition
* header file here, I'm defining my own bunch of types,
* leaving out those that are not needed.
* I also hope that they will be more in line with OpenSSL
* coding style.
*/
/* PKCS11 key object (public or private) */
typedef struct PKCS11_key_st {
char * label;
unsigned char private; /* private key present? */
unsigned char needLogin; /* login to read private key? */
EVP_PKEY * evp_key; /* initially NULL, need to call PKCS11_load_key */
void * _private;
} PKCS11_KEY;
/* PKCS11 certificate object */
typedef struct PKCS11_cert_st {
char * label;
X509 * x509;
void * _private;
} PKCS11_CERT;
/* PKCS11 token, e.g. smart card or USB key */
typedef struct PKCS11_token_st {
char * label;
char * manufacturer;
char * model;
unsigned char initialized;
unsigned char loginRequired;
unsigned char userPinSet;
unsigned char readOnly;
void * _private;
} PKCS11_TOKEN;
/* PKCS11 slot, e.g. card reader */
typedef struct PKCS11_slot_st {
char * manufacturer;
char * description;
unsigned char removable;
PKCS11_TOKEN * token; /* NULL if no token present */
void * _private;
} PKCS11_SLOT;
typedef struct PKCS11_ctx_st {
char * manufacturer;
char * description;
void * _private;
} PKCS11_CTX;
extern PKCS11_CTX * PKCS11_CTX_new();
extern int PKCS11_CTX_load(PKCS11_CTX *, const char *ident);
extern void PKCS11_CTX_unload(PKCS11_CTX *);
extern void PKCS11_CTX_free(PKCS11_CTX *);
/* Get a list of all slots */
extern int PKCS11_enumerate_slots(PKCS11_CTX *, PKCS11_SLOT **, unsigned int *);
/* Find the first slot with a token */
extern PKCS11_SLOT * PKCS11_find_token(PKCS11_CTX *);
/* Authenticate to the card */
extern int PKCS11_login(PKCS11_SLOT *, int so, char *pin);
extern int PKCS11_logout(PKCS11_SLOT *);
/* Get a list of all keys associated with this token */
extern int PKCS11_enumerate_keys(PKCS11_TOKEN *,
PKCS11_KEY **, unsigned int *);
/* Get the key type (as EVP_PKEY_XXX) */
extern int PKCS11_get_key_type(PKCS11_KEY *);
/* Get the enveloped private key */
extern EVP_PKEY * PKCS11_get_private_key(PKCS11_KEY *);
/* Find the corresponding certificate (if any) */
extern PKCS11_CERT * PKCS11_find_certificate(PKCS11_KEY *);
/* Get a list of all certificates associated with this token */
extern int PKCS11_enumerate_certs(PKCS11_TOKEN *,
PKCS11_CERT **, unsigned int *);
/* Initialize a token */
extern int PKCS11_init_token(PKCS11_TOKEN *,
char *pin, char *label);
/* Initialize the user PIN on a token */
extern int PKCS11_init_pin(PKCS11_TOKEN *, char *pin);
/* Store various objects on the token */
extern int PKCS11_generate_key(PKCS11_TOKEN *, int,
unsigned int, char *);
extern int PKCS11_store_private_key(PKCS11_TOKEN *,
EVP_PKEY *, char *);
/* Load PKCS11 error strings */
extern void ERR_load_PKCS11_strings(void);
/*
* Function and reason codes
*/
#define PKCS11_F_PKCS11_CTX_LOAD 1
#define PKCS11_F_PKCS11_ENUM_SLOTS 2
#define PKCS11_F_PKCS11_CHECK_TOKEN 3
#define PKCS11_F_PKCS11_OPEN_SESSION 4
#define PKCS11_F_PKCS11_LOGIN 5
#define PKCS11_F_PKCS11_ENUM_KEYS 6
#define PKCS11_F_PKCS11_GET_KEY 7
#define PKCS11_F_PKCS11_RSA_DECRYPT 8
#define PKCS11_F_PKCS11_RSA_ENCRYPT 9
#define PKCS11_F_PKCS11_RSA_SIGN 10
#define PKCS11_F_PKCS11_RSA_VERIFY 11
#define PKCS11_F_PKCS11_ENUM_CERTS 12
#define PKCS11_F_PKCS11_INIT_TOKEN 13
#define PKCS11_F_PKCS11_INIT_PIN 14
#define PKCS11_F_PKCS11_LOGOUT 15
#define PKCS11_F_PKCS11_STORE_PRIVATE_KEY 16
#define PKCS11_F_PKCS11_GENERATE_KEY 17
#define PKCS11_F_PKCS11_STORE_PUBLIC_KEY 18
#define PKCS11_F_PKCS11_STORE_CERTIFICATE 19
#define PKCS11_F_PKCS11_GETATTR 40
#define PKCS11_ERR_BASE 1024
#define PKCS11_LOAD_MODULE_ERROR (PKCS11_ERR_BASE+1)
#define PKCS11_MODULE_LOADED_ERROR (PKCS11_ERR_BASE+2)
#define PKCS11_SYMBOL_NOT_FOUND_ERROR (PKCS11_ERR_BASE+3)
#define PKCS11_NOT_SUPPORTED (PKCS11_ERR_BASE+4)
#define PKCS11_NO_SESSION (PKCS11_ERR_BASE+5)
#define PKCS11_KEYGEN_FAILED (PKCS11_ERR_BASE+6)
/* get private implementations of PKCS11 structures */
/*
* PKCS11_CTX: context for a PKCS11 implementation
*/
typedef struct pkcs11_ctx_private {
char * name;
void * libinfo;
CK_FUNCTION_LIST_PTR method;
CK_SESSION_HANDLE session;
int nslots;
PKCS11_SLOT * slots;
} PKCS11_CTX_private;
#define PRIVCTX(ctx) ((PKCS11_CTX_private *) (ctx->_private))
typedef struct pkcs11_slot_private {
PKCS11_CTX * parent;
unsigned char haveSession,
loggedIn;
CK_SLOT_ID id;
CK_SESSION_HANDLE session;
} PKCS11_SLOT_private;
#define PRIVSLOT(slot) ((PKCS11_SLOT_private *) (slot->_private))
#define SLOT2CTX(slot) (PRIVSLOT(slot)->parent)
typedef struct pkcs11_token_private {
PKCS11_SLOT * parent;
int nkeys, nprkeys;
PKCS11_KEY * keys;
int ncerts;
PKCS11_CERT * certs;
} PKCS11_TOKEN_private;
#define PRIVTOKEN(token) ((PKCS11_TOKEN_private *) (token->_private))
#define TOKEN2SLOT(token) (PRIVTOKEN(token)->parent)
#define TOKEN2CTX(token) SLOT2CTX(TOKEN2SLOT(token))
typedef struct pkcs11_key_ops {
int type; /* EVP_PKEY_xxx */
int (*get_public)(PKCS11_KEY *, EVP_PKEY *);
int (*get_private)(PKCS11_KEY *, EVP_PKEY *);
} PKCS11_KEY_ops;
typedef struct pkcs11_key_private {
PKCS11_TOKEN * parent;
CK_OBJECT_HANDLE object;
unsigned char id[32];
size_t id_len;
PKCS11_KEY_ops * ops;
} PKCS11_KEY_private;
#define PRIVKEY(key) ((PKCS11_KEY_private *) key->_private)
#define KEY2SLOT(key) TOKEN2SLOT(KEY2TOKEN(key))
#define KEY2TOKEN(key) (PRIVKEY(key)->parent)
#define KEY2CTX(key) TOKEN2CTX(KEY2TOKEN(key))
typedef struct pkcs11_cert_private {
PKCS11_TOKEN * parent;
CK_OBJECT_HANDLE object;
unsigned char id[32];
size_t id_len;
} PKCS11_CERT_private;
#define PRIVCERT(cert) ((PKCS11_CERT_private *) cert->_private)
/*
* Mapping Cryptoki error codes to those used internally
* by this code.
* Right now, we just map them directly, and make sure
* that the few genuine messages we use don't clash with
* PKCS#11
*/
#define pkcs11_map_err(rv) (rv)
/*
* Internal functions
*/
#define CRYPTOKI_checkerr(f, rv) \
do { if (rv) { \
PKCS11err(f, pkcs11_map_err(rv)); \
return -1; \
} } while (0)
#define CRYPTOKI_call(ctx, func_and_args) \
PRIVCTX(ctx)->method->func_and_args
/* Memory allocation */
#define PKCS11_NEW(type) \
((type *) pkcs11_malloc(sizeof(type)))
#define PKCS11_DUP(s) \
pkcs11_strdup(s, sizeof(s))
extern int PKCS11_open_session(PKCS11_SLOT *, int);
extern void pkcs11_destroy_all_slots(PKCS11_CTX *);
extern void pkcs11_destroy_slot(PKCS11_CTX *, PKCS11_SLOT *);
extern void pkcs11_destroy_keys(PKCS11_TOKEN *);
extern void pkcs11_destroy_certs(PKCS11_TOKEN *);
extern void * pkcs11_malloc(size_t);
extern char * pkcs11_strdup(char *, size_t);
extern int pkcs11_getattr(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
unsigned int, void *, unsigned int);
extern int pkcs11_getattr_s(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
unsigned int, void *, unsigned int);
extern int pkcs11_getattr_var(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
unsigned int, void *, unsigned int *);
extern int pkcs11_getattr_bn(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
unsigned int, BIGNUM **);
typedef int (*pkcs11_i2d_fn)(void *, unsigned char **);
extern void pkcs11_addattr(CK_ATTRIBUTE_PTR, int, const void *, size_t);
extern void pkcs11_addattr_int(CK_ATTRIBUTE_PTR, int, unsigned long);
extern void pkcs11_addattr_s(CK_ATTRIBUTE_PTR, int, const char *);
extern void pkcs11_addattr_bn(CK_ATTRIBUTE_PTR, int, const BIGNUM *);
extern void pkcs11_addattr_obj(CK_ATTRIBUTE_PTR, int,
pkcs11_i2d_fn, void *);
extern void pkcs11_zap_attrs(CK_ATTRIBUTE_PTR, unsigned int);
extern void * memdup(const void *, size_t);
extern PKCS11_KEY_ops pkcs11_rsa_ops;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,59 @@
#!/bin/bash
# command line parameter overrides engine to test, opensc or pkcs11
# Organization name embedded below (e.g, MTPPI) must match ca key for ca signing to work
ENGINE=pkcs11
if [[ -ne $1 ]] ;
then
ENGINE=$1;
fi;
if [[ $ENGINE == "pkcs11" ]];
then
POSTCMD="-pre MODULE_PATH:../pkcs11/.libs/opensc-pkcs11.so" ;
echo;
fi;
# self-signed certificate has a locking problem, don't try yet....
openssl << EOT
engine dynamic -vvvv -pre SO_PATH:.libs/engine_${ENGINE}.so -pre ID:${ENGINE} -pre NO_VCHECK:1 -pre LIST_ADD:1 -pre LOAD ${POSTCMD}
req -engine ${ENGINE} -new -x509 -key 45 -keyform engine -out /tmp/selfcert.crt -text
US
Maryland
Bethesda
MTPPI
Organizational Unit
Common Name
email@example.com
EOT
if [[ $? -ne 0 ]] ;
then
echo "Error generating self-signed cert"
exit 1;
fi;
#generate certificate request
# note that the test_engine.openssl has values for certificate info.
# company name needs to match ca certificate used to sign (below).
openssl << EOT
engine dynamic -vvvv -pre SO_PATH:.libs/engine_${ENGINE}.so -pre ID:${ENGINE} -pre NO_VCHECK:1 -pre LIST_ADD:1 -pre LOAD ${POSTCMD}
req -engine ${ENGINE} -md5 -new -key 45 -keyform engine -out /tmp/cert.md5.crq -text
US
Maryland
Bethesda
MTPPI
Organizational Unit
Common Name
email@example.com
EOT
if [[ $? -ne 0 ]] ;
then
echo "Error generating cert request"
exit 1;
fi;
# sign certificate, assumes ca configured
openssl ca -in /tmp/cert.md5.crq -out /tmp/test.crt || (echo "Error signing certificate" && exit 1)