sc-hsm: Added ability to initialize SmartCard-HSM using C_Initialize and C_InitPIN on PKCS#11 interface
This commit is contained in:
parent
fba298c6f4
commit
aaedef70b5
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue