Skip to content
Browse files

sc-hsm: Added ability to initialize SmartCard-HSM using C_Initialize …

…and C_InitPIN on PKCS#11 interface
  • Loading branch information...
1 parent fba298c commit aaedef70b503b49c5b731e8c4e000751c3b510bb Andreas Schwier committed with viktorTarasov
Showing with 223 additions and 3 deletions.
  1. +125 −1 src/libopensc/card-sc-hsm.c
  2. +1 −0 src/libopensc/card-sc-hsm.h
  3. +19 −0 src/libopensc/cardctl.h
  4. +26 −1 src/libopensc/pkcs15-sc-hsm.c
  5. +52 −1 src/pkcs11/framework-pkcs15.c
View
126 src/libopensc/card-sc-hsm.c
@@ -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
1 src/libopensc/card-sc-hsm.h
@@ -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
19 src/libopensc/cardctl.h
@@ -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
@@ -264,6 +266,23 @@ struct sc_cardctl_default_key {
};
/*
+ * 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
27 src/libopensc/pkcs15-sc-hsm.c
@@ -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
53 src/pkcs11/framework-pkcs15.c
@@ -22,6 +22,8 @@
#include "libopensc/log.h"
#include "libopensc/asn1.h"
+#include "libopensc/cardctl.h"
+
#include <stdlib.h>
#include <string.h>
@@ -1637,8 +1639,44 @@ 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)
{
struct sc_pkcs11_card *p11card = slot->card;
@@ -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,

0 comments on commit aaedef7

Please sign in to comment.
Something went wrong with that request. Please try again.