diff --git a/src/libopensc/card-setcos.c b/src/libopensc/card-setcos.c index 088ee965..665ee6da 100644 --- a/src/libopensc/card-setcos.c +++ b/src/libopensc/card-setcos.c @@ -2,6 +2,7 @@ * card-setcos.c: Support for PKI cards by Setec * * Copyright (C) 2001, 2002 Juha Yrjölä + * Copyright (C) 2005 Antti Tapaninen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,14 +25,26 @@ #define TYPE_GENERIC 0 #define TYPE_PKI 1 +#define TYPE_FINEID 2 static struct sc_atr_table setcos_atrs[] = { - /* this is from a Nokia branded SC */ - { "3B:1F:11:00:67:80:42:46:49:53:45:10:52:66:FF:81:90:00", NULL, TYPE_GENERIC }, + /* some Nokia branded SC */ + { "3B:1F:11:00:67:80:42:46:49:53:45:10:52:66:FF:81:90:00", NULL, NULL, TYPE_GENERIC }, /* RSA SecurID 3100 */ - { "3B:9F:94:40:1E:00:67:16:43:46:49:53:45:10:52:66:FF:81:90:00", NULL, TYPE_PKI }, - /* FinEID card */ - { "3B:9F:94:40:1E:00:67:11:43:46:49:53:45:10:52:66:FF:81:90:00", NULL, TYPE_PKI }, + { "3B:9F:94:40:1E:00:67:16:43:46:49:53:45:10:52:66:FF:81:90:00", NULL, NULL, TYPE_PKI }, + + /* FINEID 1016 (SetCOS 4.3.1B3/PKCS#15, VRK) */ + { "3b:9f:94:40:1e:00:67:00:43:46:49:53:45:10:52:66:ff:81:90:00", "ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff", NULL, TYPE_FINEID }, + /* FINEID 2032 (EIDApplet/7816-15, test) */ + { "3b:6b:00:ff:80:62:00:a2:56:46:69:6e:45:49:44", "ff:ff:00:ff:ff:ff:00:ff:ff:ff:ff:ff:ff:ff:ff", NULL, TYPE_FINEID }, + /* FINEID 2132 (EIDApplet/7816-15, OPK/EMV test) */ + { "3b:64:00:ff:80:62:00:a2", "ff:ff:00:ff:ff:ff:00:ff", NULL, TYPE_FINEID }, + /* FINEID 2064 (EIDApplet/7816-15, VRK) */ + { "3b:7b:00:00:00:80:62:00:51:56:46:69:6e:45:49:44", "ff:ff:00:ff:ff:ff:ff:f0:ff:ff:ff:ff:ff:ff:ff:ff", NULL, TYPE_FINEID }, + /* FINEID 2164 (EIDApplet/7816-15, OPK/EMV) */ + { "3b:64:00:00:80:62:00:51", "ff:ff:ff:ff:ff:ff:f0:ff", NULL, TYPE_FINEID }, + /* FINEID 2264 (EIDApplet/7816-15, OPK/EMV/AVANT) */ + { "3b:6e:00:00:00:62:00:00:57:41:56:41:4e:54:10:81:90:00", "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff", NULL, TYPE_FINEID }, { NULL } }; @@ -47,32 +60,79 @@ static int setcos_finish(struct sc_card *card) return 0; } +static int match_hist_bytes(struct sc_card *card, const char *str, size_t len) +{ + const char *src = (const char *) card->slot->atr_info.hist_bytes; + size_t srclen = card->slot->atr_info.hist_bytes_len; + size_t offset = 0; + + if (len == 0) + len = strlen(str); + if (srclen < len) + return 0; + while (srclen - offset > len) { + if (memcmp(src + offset, str, len) == 0) { + return 1; + } + offset++; + } + return 0; +} + static int setcos_match_card(struct sc_card *card) { int i; i = _sc_match_atr(card, setcos_atrs, &card->type); if (i < 0) { - const u8 *hist_bytes = card->slot->atr_info.hist_bytes; - - if (card->slot->atr_info.hist_bytes_len < 8) - return 0; - if (memcmp(hist_bytes + 4, "FISE", 4) == 0) + /* Unknown card, but has the FinEID application for sure */ + if (match_hist_bytes(card, "FinEID", 0)) { + card->type = TYPE_FINEID; return 1; + } + if (match_hist_bytes(card, "FISE", 0)) { + card->type = TYPE_GENERIC; + return 1; + } return 0; } return 1; } +static int select_fineid_app(sc_card_t * card) +{ + sc_path_t app; + int r; + + /* Regular PKCS#15 AID */ + sc_format_path ("A000000063504B43532D3135", &app); + app.type = SC_PATH_TYPE_DF_NAME; + card->ctx->suppress_errors++; + r = sc_select_file (card, &app, NULL); + card->ctx->suppress_errors--; + return r; +} + static int setcos_init(struct sc_card *card) { card->name = "SetCOS"; card->cla = 0x80; - if (card->type < 0) - card->type = TYPE_GENERIC; - - if (card->type == TYPE_PKI) { + /* Handle unknown or forced cards */ + if (card->type < 0) { +#if 1 + /* Hmm. For now, assume it's a bank card with FinEID application */ + if (match_hist_bytes(card, "AVANT", 0)) { + card->type = TYPE_FINEID; + } else +#endif + card->type = TYPE_GENERIC; + } + if (card->type == TYPE_FINEID) { + card->cla = 0x00; + select_fineid_app(card); + } + if (card->type == TYPE_PKI || card->type == TYPE_FINEID) { unsigned long flags; flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1;