diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c index 21c59241..e6c5e891 100644 --- a/src/libopensc/card-entersafe.c +++ b/src/libopensc/card-entersafe.c @@ -30,6 +30,10 @@ static struct sc_atr_table entersafe_atrs[] = { "3b:0f:00:65:46:53:05:19:05:71:df:00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff:00:00:00:00:00:00", "ePass3000", SC_CARD_TYPE_ENTERSAFE_3K, 0, NULL }, + { + "3b:9f:95:81:31:fe:9f:00:65:46:53:05:30:06:71:df:00:00:00:80:6a:82:5e", + "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:00:00:00:00", + "FTCOS/PK-01C", SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, 0, NULL }, { NULL, NULL, NULL, 0, 0, NULL } }; @@ -43,12 +47,18 @@ static struct sc_card_driver entersafe_drv = { NULL, 0, NULL }; -static u8 trans_code[] = +static u8 trans_code_3k[] = { 0x01,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, }; +static u8 trans_code_ftcos_pk_01c[] = +{ + 0x92,0x34,0x2E,0xEF, + 0x23,0x40,0x4F,0xD1, +}; + static u8 init_key[] = { 1, 2, 3, 4, @@ -118,7 +128,9 @@ static int entersafe_init(sc_card_t *card) _sc_card_add_rsa_alg(card,1024, flags, 0x10001); _sc_card_add_rsa_alg(card,2048, flags, 0x10001); + /*card->caps = SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT; */ card->caps = SC_CARD_CAP_RNG; + card->drv_data = 0; /* we need read_binary&friends with max 224 bytes per read */ @@ -674,7 +686,22 @@ static int entersafe_create_mf(sc_card_t *card, sc_entersafe_create_data * data) apdu.data=(u8*)&data->data.mf; apdu.datalen=apdu.lc=sizeof(data->data.mf); - r = entersafe_transmit_apdu(card, &apdu,trans_code,sizeof(trans_code),0,1); + switch(card->type) + { + case SC_CARD_TYPE_ENTERSAFE_3K: + { + r = entersafe_transmit_apdu(card, &apdu,trans_code_3k,sizeof(trans_code_3k),0,1); + }break; + case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C: + { + r = entersafe_transmit_apdu(card, &apdu,trans_code_ftcos_pk_01c,sizeof(trans_code_ftcos_pk_01c),0,1); + }break; + default: + { + r = SC_ERROR_INTERNAL; + }break; + } + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); return sc_check_sw(card, apdu.sw1, apdu.sw2); } @@ -920,7 +947,7 @@ static void entersafe_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num pin->max_length = 16; pin->pad_length = 16; pin->offset = 5 + num * 16; - pin->pad_char=0x00; + pin->pad_char = 0x00; } static int entersafe_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, @@ -932,7 +959,41 @@ static int entersafe_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, entersafe_init_pin_info(&data->pin2,1); data->flags |= SC_PIN_CMD_NEED_PADDING; - r = iso_ops->pin_cmd(card,data,tries_left); + if(data->cmd!=SC_PIN_CMD_UNBLOCK) + { + r = iso_ops->pin_cmd(card,data,tries_left); + } + else + { + {/*verify*/ + sc_apdu_t apdu; + u8 sbuf[0x10]={0}; + + memcpy(sbuf,data->pin1.data,data->pin1.len); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,0x20,0x00,data->pin_reference+1); + apdu.lc = apdu.datalen = sizeof(sbuf); + apdu.data = sbuf; + + r = entersafe_transmit_apdu(card, &apdu,0,0,0,0); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + } + + {/*change*/ + sc_apdu_t apdu; + u8 sbuf[0x12]={0}; + + sbuf[0] = 0x33; + sbuf[1] = 0x00; + memcpy(sbuf+2,data->pin2.data,data->pin2.len); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,0xF4,0x0B,data->pin_reference); + apdu.cla = 0x84; + apdu.lc = apdu.datalen = sizeof(sbuf); + apdu.data = sbuf; + + r = entersafe_transmit_apdu(card, &apdu,key_maintain,sizeof(key_maintain),1,1); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + } + } SC_FUNC_RETURN(card->ctx, 4, r); } @@ -961,7 +1022,23 @@ static int entersafe_erase_card(sc_card_t *card) apdu.lc=2; apdu.datalen=2; apdu.data=sbuf; - r = entersafe_transmit_apdu(card, &apdu,trans_code,sizeof(trans_code),0,1); + + switch(card->type) + { + case SC_CARD_TYPE_ENTERSAFE_3K: + { + r = entersafe_transmit_apdu(card, &apdu,trans_code_3k,sizeof(trans_code_3k),0,1); + }break; + case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C: + { + r = entersafe_transmit_apdu(card, &apdu,trans_code_ftcos_pk_01c,sizeof(trans_code_ftcos_pk_01c),0,1); + }break; + default: + { + r = SC_ERROR_INTERNAL; + }break; + } + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); } @@ -1472,10 +1549,10 @@ static int entersafe_preinstall_keys(sc_card_t *card,int (*install_rsa)(sc_card_ memset(sbuf,0,sizeof(sbuf)); sbuf[0] = 0; /* key len extern */ sbuf[1] = 16; /* key len */ - sbuf[2] = 0x0b; /* USAGE */ + sbuf[2] = 0x0B; /* USAGE */ sbuf[3] = ENTERSAFE_AC_ALWAYS; /* use AC */ sbuf[4] = 0X04; /* CHANGE AC */ - sbuf[5] = 0x14; /* UPDATE AC */ + sbuf[5] = 0x38; /* UPDATE AC */ sbuf[6] = 0x01; /* ALGO */ sbuf[7] = 0xFF; /* EC */ sbuf[8] = 0x00; /* VER */ @@ -1489,6 +1566,28 @@ static int entersafe_preinstall_keys(sc_card_t *card,int (*install_rsa)(sc_card_ SC_TEST_RET(card->ctx, r, "Preinstall user PIN failed"); } + {/* user PUK */ + memset(sbuf,0,sizeof(sbuf)); + sbuf[0] = 0; /* key len extern */ + sbuf[1] = 16; /* key len */ + sbuf[2] = 0x0B; /* USAGE */ + sbuf[3] = ENTERSAFE_AC_ALWAYS; /* use AC */ + sbuf[4] = 0X08; /* CHANGE AC */ + sbuf[5] = 0xC0; /* UPDATE AC */ + sbuf[6] = 0x01; /* ALGO */ + sbuf[7] = 0xFF; /* EC */ + sbuf[8] = 0x00; /* VER */ + + sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xF0,0x00,ENTERSAFE_USER_PIN_ID+1); + apdu.cla=0x84; + apdu.data=sbuf; + apdu.lc=apdu.datalen=0x19; + + r = entersafe_transmit_apdu(card,&apdu,init_key,sizeof(init_key),0,1); + SC_TEST_RET(card->ctx, r, "Preinstall user PUK failed"); + } + + SC_FUNC_RETURN(card->ctx,4,SC_SUCCESS); } diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index a1064226..5de1cb24 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -578,8 +578,6 @@ struct sc_rutoken_decipherinfo { #define ENTERSAFE_AC_EVERYONE 0x00 #define ENTERSAFE_AC_USER 0x04 -#define ENTERSAFE_AC_USER_ 0x08 - #define ENTERSAFE_AC_NEVER 0xC0 #define ENTERSAFE_AC_ALWAYS 0x10 diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index f9f8cc86..7af7bd77 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -144,6 +144,7 @@ enum { /* EnterSafe cards */ SC_CARD_TYPE_ENTERSAFE_BASE = 19000, SC_CARD_TYPE_ENTERSAFE_3K, + SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, }; extern sc_card_driver_t *sc_get_rutoken_driver(void); diff --git a/src/pkcs15init/entersafe.profile b/src/pkcs15init/entersafe.profile index b8d60736..25311d80 100644 --- a/src/pkcs15init/entersafe.profile +++ b/src/pkcs15init/entersafe.profile @@ -12,6 +12,7 @@ cardinfo { option default { macros { pin-flags = initialized, needs-padding; + min-pin-length = 4; df_acl = *=NEVER; protected = *=$PIN,READ=NONE; dir-size = 128; @@ -49,21 +50,25 @@ PIN so-pin { reference = 1; attempts = 3; flags = $pin-flags; + min-length = $min-pin-length; } PIN so-puk { reference = 1; attempts = 3; flags = $pin-flags; + min-length = $min-pin-length; } PIN user-pin { reference = 1; attempts = 3; flags = $pin-flags; + min-length = $min-pin-length; } PIN user-puk { reference = 1; attempts = 3; flags = $pin-flags; + min-length = $min-pin-length; } # Additional filesystem info. @@ -147,7 +152,6 @@ filesystem { } EF public-key { file-id = 3003; - size = 320; structure = transparent; ACL = *=NEVER,READ=NONE,UPDATE=$PIN; } @@ -173,16 +177,7 @@ filesystem { structure = transparent; ACL = *=NEVER,READ=NONE,UPDATE=$PIN; } - - # private data objects are stored in transparent EFs. - EF data { - file-id = 3401; - structure = transparent; - ACL = *=NEVER,READ=$PIN,UPDATE=$PIN; - } - } - } } } diff --git a/src/pkcs15init/pkcs15-entersafe.c b/src/pkcs15init/pkcs15-entersafe.c index d86a90d3..acce9293 100644 --- a/src/pkcs15init/pkcs15-entersafe.c +++ b/src/pkcs15init/pkcs15-entersafe.c @@ -258,23 +258,45 @@ static int entersafe_create_pin(sc_profile_t *profile, sc_card_t *card, { int r; sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data; - sc_entersafe_wkey_data data; SC_FUNC_CALLED(card->ctx, 1); - if (!pin || !pin_len || pin_len > 16) - return SC_ERROR_INVALID_ARGUMENTS; + {/*pin*/ + sc_entersafe_wkey_data data; - data.key_id=pin_info->reference; - data.usage=0x0B; - data.key_data.symmetric.EC=0x33; - data.key_data.symmetric.ver=0x00; - /* pad pin with 0 */ - memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val)); - memcpy(data.key_data.symmetric.key_val, pin, pin_len); - data.key_data.symmetric.key_len=16; + if (!pin || !pin_len || pin_len > 16) + return SC_ERROR_INVALID_ARGUMENTS; + + data.key_id=pin_info->reference; + data.usage=0x0B; + data.key_data.symmetric.EC=0x33; + data.key_data.symmetric.ver=0x00; + /* pad pin with 0 */ + memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val)); + memcpy(data.key_data.symmetric.key_val, pin, pin_len); + data.key_data.symmetric.key_len=16; + + r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); + } + + {/*puk*/ + sc_entersafe_wkey_data data; + + if (!puk || !puk_len || puk_len > 16) + return SC_ERROR_INVALID_ARGUMENTS; + + data.key_id=pin_info->reference+1; + data.usage=0x0B; + data.key_data.symmetric.EC=0x33; + data.key_data.symmetric.ver=0x00; + /* pad pin with 0 */ + memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val)); + memcpy(data.key_data.symmetric.key_val, puk, puk_len); + data.key_data.symmetric.key_len=16; + + r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); + } - r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); SC_FUNC_RETURN(card->ctx,4,r); }