sc-hsm: Added ability to initialize SmartCard-HSM using C_Initialize and C_InitPIN on PKCS#11 interface

This commit is contained in:
Andreas Schwier 2012-10-14 21:01:28 +02:00 committed by Viktor Tarasov
parent fba298c6f4
commit aaedef70b5
5 changed files with 223 additions and 3 deletions

View File

@ -134,6 +134,21 @@ static int sc_hsm_match_card(struct sc_card *card)
static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left)
{
sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
if (data->pin_reference == 0x88) {
// Save SO PIN for later use in init pin
memcpy(priv->initpw, data->pin1.data, sizeof(priv->initpw));
return SC_SUCCESS;
}
return (*iso_ops->pin_cmd)(card, data, tries_left);
}
static int sc_hsm_read_binary(sc_card_t *card,
unsigned int idx, u8 *buf, size_t count,
unsigned long flags)
@ -560,7 +575,111 @@ static int sc_hsm_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
serial->len = strlen(priv->serialno);
strncpy(serial->value, priv->serialno, sizeof(serial->value));
return 0;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *params)
{
sc_context_t *ctx = card->ctx;
int r, i;
sc_apdu_t apdu;
u8 ibuff[50], *p;
LOG_FUNC_CALLED(card->ctx);
if (params->so_pin_len != 16) {
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "SO PIN wrong length (!=16)");
}
p = ibuff;
*p++ = 0x80; // Options
*p++ = 0x02;
*p++ = 0x00;
*p++ = 0x01;
*p++ = 0x81; // User PIN
*p++ = 0x06; // Default value, later changed with C_InitPIN
// We use only 6 of the 16 bytes init password for the initial user PIN
memcpy(p, params->so_pin, 6);
p += 6;
*p++ = 0x82; // Initialization code
*p++ = 0x08;
memset(p, 0, 8);
for (i = 0; i < 16; i++) {
*p <<= 4;
*p |= params->so_pin[i] & 0xf;
if (i & 1)
p++;
}
*p++ = 0x91; // User PIN retry counter
*p++ = 0x01;
*p++ = 0x03;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x50, 0x00, 0x00);
apdu.cla = 0x80;
apdu.data = ibuff;
apdu.datalen = p - ibuff;
apdu.lc = apdu.datalen;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r == SC_ERROR_NOT_ALLOWED) {
r = SC_ERROR_PIN_CODE_INCORRECT;
}
LOG_TEST_RET(ctx, r, "Check SW error");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
static int sc_hsm_init_pin(sc_card_t *card, sc_cardctl_pkcs11_init_pin_t *params)
{
sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
sc_context_t *ctx = card->ctx;
int r;
sc_apdu_t apdu;
u8 ibuff[50], *p;
LOG_FUNC_CALLED(card->ctx);
if (params->pin_len > 16) {
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "User PIN too long");
}
p = ibuff;
// We use only 6 of the 8 bytes init password for the initial user PIN
memcpy(p, priv->initpw, 6);
p += 6;
memcpy(p, params->pin, params->pin_len);
p += params->pin_len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x00, 0x81);
apdu.data = ibuff;
apdu.datalen = p - ibuff;
apdu.lc = apdu.datalen;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(ctx, r, "Check SW error");
memset(priv->initpw, 0, sizeof(priv->initpw));
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@ -609,6 +728,10 @@ static int sc_hsm_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
switch (cmd) {
case SC_CARDCTL_GET_SERIALNR:
return sc_hsm_get_serialnr(card, (sc_serial_number_t *)ptr);
case SC_CARDCTL_PKCS11_INIT_TOKEN:
return sc_hsm_init_token(card, (sc_cardctl_pkcs11_init_token_t *)ptr);
case SC_CARDCTL_PKCS11_INIT_PIN:
return sc_hsm_init_pin(card, (sc_cardctl_pkcs11_init_pin_t *)ptr);
case SC_CARDCTL_SC_HSM_GENERATE_KEY:
return sc_hsm_generate_keypair(card, (sc_cardctl_sc_hsm_keygen_info_t *)ptr);
}
@ -693,6 +816,7 @@ static struct sc_card_driver * sc_get_driver(void)
sc_hsm_ops.init = sc_hsm_init;
sc_hsm_ops.finish = sc_hsm_finish;
sc_hsm_ops.card_ctl = sc_hsm_card_ctl;
sc_hsm_ops.pin_cmd = sc_hsm_pin_cmd;
/* no record oriented file services */
sc_hsm_ops.read_record = NULL;

View File

@ -54,6 +54,7 @@ typedef struct sc_hsm_private_data {
u8 algorithm;
int noExtLength;
char *serialno;
char initpw[6]; // Initial user PIN set at initialization (first 6 digits of token pin)
} sc_hsm_private_data_t;

View File

@ -42,6 +42,8 @@ enum {
SC_CARDCTL_GET_SERIALNR,
SC_CARDCTL_GET_SE_INFO,
SC_CARDCTL_GET_CHV_REFERENCE_IN_SE,
SC_CARDCTL_PKCS11_INIT_TOKEN,
SC_CARDCTL_PKCS11_INIT_PIN,
/*
* GPK specific calls
@ -263,6 +265,23 @@ struct sc_cardctl_default_key {
u8 * key_data; /* out: key data */
};
/*
* Generic cardctl - initialize token using PKCS#11 style
*/
typedef struct sc_cardctl_pkcs11_init_token {
const char * so_pin;
size_t so_pin_len;
const char * label;
} sc_cardctl_pkcs11_init_token_t;
/*
* Generic cardctl - set pin using PKCS#11 style
*/
typedef struct sc_cardctl_pkcs11_init_pin {
const char * pin;
size_t pin_len;
} sc_cardctl_pkcs11_init_pin_t;
/*
* GPK lock file.
* Parent DF of file must be selected.

View File

@ -473,7 +473,7 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
LOG_FUNC_CALLED(card->ctx);
p15card->tokeninfo->label = strdup("SmartCard-HSM");
p15card->tokeninfo->manufacturer_id = strdup("CardContact");
p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de");
appinfo = calloc(1, sizeof(struct sc_app_info));
@ -552,6 +552,31 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
if (r < 0)
LOG_FUNC_RETURN(card->ctx, r);
memset(&pin_info, 0, sizeof(pin_info));
memset(&pin_obj, 0, sizeof(pin_obj));
pin_info.auth_id.len = 1;
pin_info.auth_id.value[0] = 2;
pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
pin_info.attrs.pin.reference = 0x88;
pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_CHANGE_DISABLED|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED|SC_PKCS15_PIN_FLAG_SO_PIN;
pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_BCD;
pin_info.attrs.pin.min_length = 16;
pin_info.attrs.pin.stored_length = 0;
pin_info.attrs.pin.max_length = 16;
pin_info.attrs.pin.pad_char = '\0';
pin_info.tries_left = 3;
pin_info.max_tries = 3;
strlcpy(pin_obj.label, "SOPIN", sizeof(pin_obj.label));
pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
if (r < 0)
LOG_FUNC_RETURN(card->ctx, r);
filelistlength = sc_list_files(card, filelist, sizeof(filelist));
LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier");

View File

@ -22,6 +22,8 @@
#include "libopensc/log.h"
#include "libopensc/asn1.h"
#include "libopensc/cardctl.h"
#include <stdlib.h>
#include <string.h>
@ -1637,7 +1639,43 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot,
return sc_to_cryptoki_error(rc, "C_SetPIN");
}
#ifdef USE_PKCS15_INIT
static CK_RV
pkcs15_initialize(struct sc_pkcs11_card *p11card, void *ptr,
CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
CK_UTF8CHAR_PTR pLabel)
{
struct sc_cardctl_pkcs11_init_token args;
int rv;
memset(&args, 0, sizeof(args));
args.so_pin = pPin;
args.so_pin_len = ulPinLen;
args.label = (const char *) pLabel;
rv = sc_card_ctl(p11card->card, SC_CARDCTL_PKCS11_INIT_TOKEN, &args);
if (rv == SC_ERROR_NOT_SUPPORTED)
return CKR_FUNCTION_NOT_SUPPORTED;
if (rv < 0)
return sc_to_cryptoki_error(rv, "C_InitToken");
rv = card_removed(p11card->reader);
if (rv != SC_SUCCESS)
return rv;
rv = card_detect_all();
if (rv != SC_SUCCESS)
return rv;
return CKR_OK;
}
static CK_RV
pkcs15_init_pin(struct sc_pkcs11_slot *slot, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
{
@ -1647,8 +1685,21 @@ pkcs15_init_pin(struct sc_pkcs11_slot *slot, CK_CHAR_PTR pPin, CK_ULONG ulPinLen
struct sc_profile *profile = NULL;
struct sc_pkcs15_object *auth_obj = NULL;
struct sc_pkcs15_auth_info *auth_info = NULL;
struct sc_cardctl_pkcs11_init_pin p11args;
int rc;
memset(&p11args, 0, sizeof(p11args));
p11args.pin = pPin;
p11args.pin_len = ulPinLen;
rc = sc_card_ctl(p11card->card, SC_CARDCTL_PKCS11_INIT_PIN, &p11args);
if (rc != SC_ERROR_NOT_SUPPORTED) {
if (rc == SC_SUCCESS)
return CKR_OK;
return sc_to_cryptoki_error(rc, "C_InitPin");
}
sc_log(context, "Init PIN: pin %p:%d; unblock style %i", pPin, ulPinLen, sc_pkcs11_conf.pin_unblock_style);
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[slot->fw_data_idx];
@ -2802,7 +2853,7 @@ struct sc_pkcs11_framework_ops framework_pkcs15 = {
pkcs15_login,
pkcs15_logout,
pkcs15_change_pin,
NULL, /* init_token */
pkcs15_initialize,
#ifdef USE_PKCS15_INIT
pkcs15_init_pin,
pkcs15_create_object,