diff --git a/src/libopensc/card-rtecp.c b/src/libopensc/card-rtecp.c index cbe39568..d0634d04 100644 --- a/src/libopensc/card-rtecp.c +++ b/src/libopensc/card-rtecp.c @@ -486,12 +486,36 @@ static int rtecp_reset_retry_counter(sc_card_t *card, unsigned int type, sc_apdu_t apdu; int r; - (void)type, (void)puk, (void)puklen, (void)newref, (void)newlen; /* no warning */ + (void)type, (void)puk, (void)puklen; /* no warning */ assert(card && card->ctx); + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2C, 0x03, ref_qualifier); r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Unblock card failed"); + + if (newref && newlen) { + u8 tmp[2], buf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p = buf; + + tmp[0] = (newlen >> 8) & 0xFF; + tmp[1] = newlen & 0xFF; + sc_asn1_put_tag(0x80, tmp, sizeof(tmp), p, sizeof(buf) - (p - buf), &p); + r = sc_asn1_put_tag(0xA5, newref, newlen, p, sizeof(buf) - (p - buf), &p); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Invalid new PIN length"); + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x01, ref_qualifier); + apdu.lc = p - buf; + apdu.data = buf; + apdu.datalen = p - buf; + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Set PIN failed"); + } + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); } diff --git a/src/pkcs15init/pkcs15-rtecp.c b/src/pkcs15init/pkcs15-rtecp.c index ae9167c4..f41c4c58 100644 --- a/src/pkcs15init/pkcs15-rtecp.c +++ b/src/pkcs15init/pkcs15-rtecp.c @@ -168,12 +168,13 @@ static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, { sc_context_t *ctx; sc_pkcs15_pin_info_t *pin_info; - sc_file_t *file; + sc_file_t *file = NULL; /* GCHV min-length Flags Attempts Reserve */ unsigned char prop[] = { 0x01, '?', 0x01, '?', 0, 0 }; /* AccessMode Unblock Change Delete */ unsigned char sec[15] = { 0x43, '?', '?', 0, 0, 0, 0, 0xFF }; - int r; + char pin_sname[0x10]; + int r, reset_by_sopin = 0; (void)puk; /* no warning */ if (!profile || !p15card || !p15card->card || !p15card->card->ctx || !df @@ -182,6 +183,7 @@ static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, ctx = p15card->card->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); + if (puk_len != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Do not enter User unblocking PIN (PUK): %s\n", @@ -196,6 +198,25 @@ static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, " (Rutoken ECP) PINs\n", pin_info->reference); return SC_ERROR_NOT_SUPPORTED; } + + snprintf(pin_sname, sizeof(pin_sname), "CHV%i", pin_info->reference); + if (pin_info->reference == RTECP_USER_PIN_REF) { + r = sc_profile_get_file(profile, pin_sname, &file); + if (!r) { + const struct sc_acl_entry *acl = NULL; + + r = sc_pkcs15init_fixup_file(profile, p15card, file); + SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot fixup the ACLs of PIN file"); + + acl = sc_file_get_acl_entry(file, SC_AC_OP_PIN_RESET); + if (acl && acl->method == SC_AC_CHV && acl->key_ref == RTECP_SO_PIN_REF) { + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Allow reset of User PIN with SoPIN\n"); + reset_by_sopin = 1; + } + sc_file_free(file); + } + } + file = sc_file_new(); if (!file) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); @@ -203,7 +224,7 @@ static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, file->size = pin_len; assert(sizeof(sec)/sizeof(sec[0]) > 2); sec[1] = (pin_info->reference == RTECP_SO_PIN_REF) ? 0xFF : RTECP_SO_PIN_REF; - sec[2] = (unsigned char)pin_info->reference; + sec[2] = (unsigned char)pin_info->reference | (reset_by_sopin ? RTECP_SO_PIN_REF : 0); r = sc_file_set_sec_attr(file, sec, sizeof(sec)); if (r == SC_SUCCESS) { diff --git a/src/pkcs15init/rutoken_ecp.profile b/src/pkcs15init/rutoken_ecp.profile index 2f3fff12..3ff4d3fa 100644 --- a/src/pkcs15init/rutoken_ecp.profile +++ b/src/pkcs15init/rutoken_ecp.profile @@ -23,6 +23,8 @@ pkcs15 { encode-df-length = no; # Have a lastUpdate field in the EF(TokenInfo)? do-last-update = yes; + + pkcs15-id-style = mozilla; } # Default settings. @@ -45,8 +47,8 @@ option default { PIN user-pin { auth-id = 2; reference = 2; - attempts = 10; - min-length = 8; + attempts = 5; + min-length = 4; max-length = 32; flags = case-sensitive, initialized; } @@ -69,6 +71,10 @@ PIN so-puk { } filesystem { + EF CHV2 { + file-id = 0002; + ACL = *=NEVER, UPDATE=$SOPIN, PIN-RESET=$SOPIN; + } DF MF { path = 3F00;