| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | #include "internal.h" |
|---|
| 24 | #include "cardctl.h" |
|---|
| 25 | #include <stdlib.h> |
|---|
| 26 | #include <string.h> |
|---|
| 27 | |
|---|
| 28 | #include <opensc/asn1.h> |
|---|
| 29 | |
|---|
| 30 | static struct sc_atr_table setcos_atrs[] = { |
|---|
| 31 | Â Â Â Â |
|---|
| 32 | Â Â Â Â { "3B:1F:11:00:67:80:42:46:49:53:45:10:52:66:FF:81:90:00", NULL, NULL, SC_CARD_TYPE_SETCOS_GENERIC, 0, NULL }, |
|---|
| 33 | Â Â Â Â |
|---|
| 34 | Â Â Â Â { "3B:9F:94:40:1E:00:67:16:43:46:49:53:45:10:52:66:FF:81:90:00", NULL, NULL, SC_CARD_TYPE_SETCOS_PKI, 0, NULL }, |
|---|
| 35 | |
|---|
| 36 | Â Â Â Â |
|---|
| 37 | Â Â Â Â { "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, SC_CARD_TYPE_SETCOS_FINEID, SC_CARD_FLAG_RNG, NULL }, |
|---|
| 38 | Â Â Â Â |
|---|
| 39 | Â Â Â Â { "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, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 40 | Â Â Â Â |
|---|
| 41 | Â Â Â Â { "3b:64:00:ff:80:62:00:a2", "ff:ff:00:ff:ff:ff:00:ff", NULL, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 42 | Â Â Â Â |
|---|
| 43 | Â Â Â Â { "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, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 44 | Â Â Â Â |
|---|
| 45 | Â Â Â Â { "3b:64:00:00:80:62:00:51", "ff:ff:ff:ff:ff:ff:f0:ff", NULL, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 46 | Â Â Â Â |
|---|
| 47 | Â Â Â Â { "3b:6e:00:00:00:62:00:00:57:41:56:41:4e:54:10:81:90:00", NULL, NULL, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 48 | Â Â Â Â { "3b:7b:94:00:00:80:62:11:51:56:46:69:6e:45:49:44", NULL, NULL, SC_CARD_TYPE_SETCOS_FINEID_V2, 0, NULL }, |
|---|
| 49 | Â Â Â Â |
|---|
| 50 | Â Â Â Â { "3b:9f:94:80:1f:c3:00:68:10:44:05:01:46:49:53:45:31:c8:07:90:00:18", NULL, NULL, SC_CARD_TYPE_SETCOS_NIDEL, 0, NULL }, |
|---|
| 51 | Â Â Â Â |
|---|
| 52 | Â Â Â Â { "3b:9f:94:80:1f:c3:00:68:11:44:05:01:46:49:53:45:31:c8:00:00:00:00", "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00", NULL, SC_CARD_TYPE_SETCOS_44, 0, NULL }, |
|---|
| 53 | Â Â Â Â { NULL, NULL, NULL, 0, 0, NULL } |
|---|
| 54 | }; |
|---|
| 55 | |
|---|
| 56 | #define SETCOS_IS_EID_APPLET(card) ((card)->type == SC_CARD_TYPE_SETCOS_EID_V2_0 || (card)->type == SC_CARD_TYPE_SETCOS_EID_V2_1) |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | #define SETEC_LCSI_CREATE   0x01 |
|---|
| 60 | #define SETEC_LCSI_INIT    0x03 |
|---|
| 61 | #define SETEC_LCSI_ACTIVATED  0x07 |
|---|
| 62 | #define SETEC_LCSI_DEACTIVATE 0x06 |
|---|
| 63 | #define SETEC_LCSI_TEMINATE  0x0F |
|---|
| 64 | |
|---|
| 65 | static struct sc_card_operations setcos_ops; |
|---|
| 66 | static struct sc_card_driver setcos_drv = { |
|---|
| 67 | Â Â Â Â "Setec cards", |
|---|
| 68 | Â Â Â Â "setcos", |
|---|
| 69 | Â Â Â Â &setcos_ops, |
|---|
| 70 | Â Â Â Â NULL, 0, NULL |
|---|
| 71 | }; |
|---|
| 72 | |
|---|
| 73 | static int setcos_finish(sc_card_t *card) |
|---|
| 74 | { |
|---|
| 75 |     return 0; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | static int match_hist_bytes(sc_card_t *card, const char *str, size_t len) |
|---|
| 79 | { |
|---|
| 80 |     const char *src = (const char *) card->slot->atr_info.hist_bytes; |
|---|
| 81 | Â Â Â Â size_t srclen = card->slot->atr_info.hist_bytes_len; |
|---|
| 82 | Â Â Â Â size_t offset = 0; |
|---|
| 83 | |
|---|
| 84 |     if (len == 0) |
|---|
| 85 | Â Â Â Â Â Â Â Â len = strlen(str); |
|---|
| 86 |     if (srclen < len) |
|---|
| 87 |         return 0; |
|---|
| 88 |     while (srclen - offset > len) { |
|---|
| 89 |         if (memcmp(src + offset, str, len) == 0) { |
|---|
| 90 |             return 1; |
|---|
| 91 | Â Â Â Â Â Â Â Â } |
|---|
| 92 | Â Â Â Â Â Â Â Â offset++; |
|---|
| 93 | Â Â Â Â } |
|---|
| 94 |     return 0; |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | static int setcos_match_card(sc_card_t *card) |
|---|
| 98 | { |
|---|
| 99 | Â Â Â Â sc_apdu_t apdu; |
|---|
| 100 | Â Â Â Â u8 buf[6]; |
|---|
| 101 |     int i; |
|---|
| 102 | |
|---|
| 103 | Â Â Â Â i = _sc_match_atr(card, setcos_atrs, &card->type); |
|---|
| 104 |     if (i < 0) { |
|---|
| 105 | Â Â Â Â Â Â Â Â |
|---|
| 106 |         if (match_hist_bytes(card, "FinEID", 0)) { |
|---|
| 107 | Â Â Â Â Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_FINEID_V2; |
|---|
| 108 |             return 1; |
|---|
| 109 | Â Â Â Â Â Â Â Â } |
|---|
| 110 |         if (match_hist_bytes(card, "FISE", 0)) { |
|---|
| 111 | Â Â Â Â Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_GENERIC; |
|---|
| 112 |             return 1; |
|---|
| 113 | Â Â Â Â Â Â Â Â } |
|---|
| 114 | Â Â Â Â Â Â Â Â |
|---|
| 115 | Â Â Â Â Â Â Â Â sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0xDF, 0x30); |
|---|
| 116 | Â Â Â Â Â Â Â Â apdu.cla = 0x00; |
|---|
| 117 | Â Â Â Â Â Â Â Â apdu.resp = buf; |
|---|
| 118 | Â Â Â Â Â Â Â Â apdu.resplen = 5; |
|---|
| 119 | Â Â Â Â Â Â Â Â apdu.le = 5; |
|---|
| 120 | Â Â Â Â Â Â Â Â i = sc_transmit_apdu(card, &apdu); |
|---|
| 121 |         if (i == 0 && apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && apdu.resplen == 5) { |
|---|
| 122 |             if (memcmp(buf, "v2.0", 4) == 0) |
|---|
| 123 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_EID_V2_0; |
|---|
| 124 |             else if (memcmp(buf, "v2.1", 4) == 0) |
|---|
| 125 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_EID_V2_1; |
|---|
| 126 |             else { |
|---|
| 127 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[sizeof(buf) - 1] = '\0'; |
|---|
| 128 |                 sc_debug(card->ctx, "SetCOS EID applet %s is not supported", (char *) buf); |
|---|
| 129 |                 return 0; |
|---|
| 130 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 131 |             return 1; |
|---|
| 132 | Â Â Â Â Â Â Â Â } |
|---|
| 133 | |
|---|
| 134 |         return 0; |
|---|
| 135 | Â Â Â Â } |
|---|
| 136 | Â Â Â Â card->flags = setcos_atrs[i].flags; |
|---|
| 137 |     return 1; |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | static int select_pkcs15_app(sc_card_t * card) |
|---|
| 141 | { |
|---|
| 142 | Â Â Â Â sc_path_t app; |
|---|
| 143 |     int r; |
|---|
| 144 | |
|---|
| 145 | Â Â Â Â |
|---|
| 146 | Â Â Â Â sc_format_path("A000000063504B43532D3135", &app); |
|---|
| 147 | Â Â Â Â app.type = SC_PATH_TYPE_DF_NAME; |
|---|
| 148 | Â Â Â Â sc_ctx_suppress_errors_on(card->ctx); |
|---|
| 149 | Â Â Â Â r = sc_select_file(card, &app, NULL); |
|---|
| 150 | Â Â Â Â sc_ctx_suppress_errors_off(card->ctx); |
|---|
| 151 |     return r; |
|---|
| 152 | } |
|---|
| 153 | |
|---|
| 154 | static int setcos_init(sc_card_t *card) |
|---|
| 155 | { |
|---|
| 156 | Â Â Â Â card->name = "SetCOS"; |
|---|
| 157 | |
|---|
| 158 | Â Â Â Â |
|---|
| 159 |     if (card->type < 0) { |
|---|
| 160 | Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_GENERIC; |
|---|
| 161 | #if 0 |
|---|
| 162 | Â Â Â Â Â Â Â Â |
|---|
| 163 |         if (match_hist_bytes(card, "AVANT", 0)) |
|---|
| 164 | Â Â Â Â Â Â Â Â Â Â Â Â card->type = SC_CARD_TYPE_SETCOS_FINEID_V2; |
|---|
| 165 | #endif |
|---|
| 166 | Â Â Â Â } |
|---|
| 167 | |
|---|
| 168 |     switch (card->type) { |
|---|
| 169 |     case SC_CARD_TYPE_SETCOS_FINEID: |
|---|
| 170 |     case SC_CARD_TYPE_SETCOS_FINEID_V2: |
|---|
| 171 |     case SC_CARD_TYPE_SETCOS_NIDEL: |
|---|
| 172 | Â Â Â Â Â Â Â Â card->cla = 0x00; |
|---|
| 173 | Â Â Â Â Â Â Â Â select_pkcs15_app(card); |
|---|
| 174 |         if (card->flags & SC_CARD_FLAG_RNG) |
|---|
| 175 | Â Â Â Â Â Â Â Â Â Â Â Â card->caps |= SC_CARD_CAP_RNG; |
|---|
| 176 | Â Â Â Â Â Â Â Â break; |
|---|
| 177 |     case SC_CARD_TYPE_SETCOS_44: |
|---|
| 178 |     case SC_CARD_TYPE_SETCOS_EID_V2_0: |
|---|
| 179 |     case SC_CARD_TYPE_SETCOS_EID_V2_1: |
|---|
| 180 | Â Â Â Â Â Â Â Â card->cla = 0x00; |
|---|
| 181 | Â Â Â Â Â Â Â Â card->caps |= SC_CARD_CAP_USE_FCI_AC; |
|---|
| 182 | Â Â Â Â Â Â Â Â card->caps |= SC_CARD_CAP_RNG; |
|---|
| 183 | Â Â Â Â Â Â Â Â card->caps |= SC_CARD_FLAG_ONBOARD_KEY_GEN; |
|---|
| 184 | Â Â Â Â Â Â Â Â break; |
|---|
| 185 | Â Â Â Â default: |
|---|
| 186 | Â Â Â Â Â Â Â Â |
|---|
| 187 | Â Â Â Â Â Â Â Â card->cla = 0x80;Â Â Â Â |
|---|
| 188 | Â Â Â Â Â Â Â Â |
|---|
| 189 | Â Â Â Â Â Â Â Â card->caps |= SC_CARD_CAP_RNG; |
|---|
| 190 | Â Â Â Â Â Â Â Â break; |
|---|
| 191 | Â Â Â Â } |
|---|
| 192 | |
|---|
| 193 |     switch (card->type) { |
|---|
| 194 |     case SC_CARD_TYPE_SETCOS_PKI: |
|---|
| 195 |     case SC_CARD_TYPE_SETCOS_FINEID: |
|---|
| 196 |     case SC_CARD_TYPE_SETCOS_FINEID_V2: |
|---|
| 197 | Â Â Â Â Â Â Â Â { |
|---|
| 198 |             unsigned long flags; |
|---|
| 199 | |
|---|
| 200 | Â Â Â Â Â Â Â Â Â Â Â Â flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; |
|---|
| 201 | Â Â Â Â Â Â Â Â Â Â Â Â flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1; |
|---|
| 202 | |
|---|
| 203 | Â Â Â Â Â Â Â Â Â Â Â Â _sc_card_add_rsa_alg(card, 1024, flags, 0); |
|---|
| 204 | Â Â Â Â Â Â Â Â } |
|---|
| 205 | Â Â Â Â Â Â Â Â break; |
|---|
| 206 |     case SC_CARD_TYPE_SETCOS_44: |
|---|
| 207 |     case SC_CARD_TYPE_SETCOS_NIDEL: |
|---|
| 208 |     case SC_CARD_TYPE_SETCOS_EID_V2_0: |
|---|
| 209 |     case SC_CARD_TYPE_SETCOS_EID_V2_1: |
|---|
| 210 | Â Â Â Â Â Â Â Â { |
|---|
| 211 |             unsigned long flags; |
|---|
| 212 | |
|---|
| 213 | Â Â Â Â Â Â Â Â Â Â Â Â flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1; |
|---|
| 214 | Â Â Â Â Â Â Â Â Â Â Â Â flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1; |
|---|
| 215 | Â Â Â Â Â Â Â Â Â Â Â Â flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; |
|---|
| 216 | |
|---|
| 217 | Â Â Â Â Â Â Â Â Â Â Â Â _sc_card_add_rsa_alg(card, 512, flags, 0); |
|---|
| 218 | Â Â Â Â Â Â Â Â Â Â Â Â _sc_card_add_rsa_alg(card, 768, flags, 0); |
|---|
| 219 | Â Â Â Â Â Â Â Â Â Â Â Â _sc_card_add_rsa_alg(card, 1024, flags, 0); |
|---|
| 220 | Â Â Â Â Â Â Â Â } |
|---|
| 221 | Â Â Â Â Â Â Â Â break; |
|---|
| 222 | Â Â Â Â } |
|---|
| 223 |     return 0; |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | static const struct sc_card_operations *iso_ops = NULL; |
|---|
| 227 | |
|---|
| 228 | static int setcos_construct_fci_44(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen) |
|---|
| 229 | { |
|---|
| 230 | Â Â Â Â u8 *p = out; |
|---|
| 231 | Â Â Â Â u8 buf[64]; |
|---|
| 232 |     const u8 *pin_key_info; |
|---|
| 233 |     int len; |
|---|
| 234 | |
|---|
| 235 | Â Â Â Â |
|---|
| 236 | Â Â Â Â *p++ = 0x6F; |
|---|
| 237 | Â Â Â Â p++; |
|---|
| 238 | |
|---|
| 239 | Â Â Â Â |
|---|
| 240 |     if (SETCOS_IS_EID_APPLET(card) && |
|---|
| 241 | Â Â Â Â Â Â (file->type == SC_FILE_TYPE_INTERNAL_EF || |
|---|
| 242 | Â Â Â Â Â Â Â (file->type == SC_FILE_TYPE_WORKING_EF && file->ef_structure == 0x22))) |
|---|
| 243 | Â Â Â Â Â Â Â Â buf[0] = buf[1] = 0x00; |
|---|
| 244 |     else { |
|---|
| 245 | Â Â Â Â Â Â Â Â buf[0] = (file->size >> 8) & 0xFF; |
|---|
| 246 | Â Â Â Â Â Â Â Â buf[1] = file->size & 0xFF; |
|---|
| 247 | Â Â Â Â } |
|---|
| 248 | Â Â Â Â sc_asn1_put_tag(0x81, buf, 2, p, *outlen - (p - out), &p); |
|---|
| 249 | |
|---|
| 250 | Â Â Â Â |
|---|
| 251 |     if (file->type_attr_len) { |
|---|
| 252 | Â Â Â Â Â Â Â Â memcpy(buf, file->type_attr, file->type_attr_len); |
|---|
| 253 | Â Â Â Â Â Â Â Â sc_asn1_put_tag(0x82, buf, file->type_attr_len, p, *outlen - (p - out), &p); |
|---|
| 254 |     } else { |
|---|
| 255 | Â Â Â Â Â Â Â Â u8Â Â Â bLen = 1; |
|---|
| 256 | |
|---|
| 257 | Â Â Â Â Â Â Â Â buf[0] = file->shareable ? 0x40 : 0; |
|---|
| 258 |         switch (file->type) { |
|---|
| 259 |         case SC_FILE_TYPE_INTERNAL_EF:             |
|---|
| 260 | Â Â Â Â Â Â Â Â Â Â Â Â buf[0] = 0x11;Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 261 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 262 |         case SC_FILE_TYPE_WORKING_EF: |
|---|
| 263 |             if (file->ef_structure == 0x22) {        |
|---|
| 264 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[0] = 0x0A;Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 265 |                 if (SETCOS_IS_EID_APPLET(card)) |
|---|
| 266 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bLen = 1; |
|---|
| 267 |                 else { |
|---|
| 268 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 269 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bLen = 5; |
|---|
| 270 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[1] = 0x41;Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 271 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[2] = file->record_length >> 8;Â Â Â |
|---|
| 272 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[3] = file->record_length & 0xFF; |
|---|
| 273 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[4] = file->size / file->record_length; |
|---|
| 274 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 275 |             } else { |
|---|
| 276 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â buf[0] |= file->ef_structure & 7;Â Â Â Â |
|---|
| 277 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 278 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 279 |         case SC_FILE_TYPE_DF:  |
|---|
| 280 | Â Â Â Â Â Â Â Â Â Â Â Â buf[0] = 0x38; |
|---|
| 281 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 282 | Â Â Â Â Â Â Â Â default: |
|---|
| 283 |             return SC_ERROR_NOT_SUPPORTED; |
|---|
| 284 | Â Â Â Â Â Â Â Â } |
|---|
| 285 | Â Â Â Â Â Â Â Â sc_asn1_put_tag(0x82, buf, bLen, p, *outlen - (p - out), &p); |
|---|
| 286 | Â Â Â Â } |
|---|
| 287 | |
|---|
| 288 | Â Â Â Â |
|---|
| 289 | Â Â Â Â buf[0] = (file->id >> 8) & 0xFF; |
|---|
| 290 | Â Â Â Â buf[1] = file->id & 0xFF; |
|---|
| 291 | Â Â Â Â sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p); |
|---|
| 292 | |
|---|
| 293 | Â Â Â Â |
|---|
| 294 |     if (file->type == SC_FILE_TYPE_DF) { |
|---|
| 295 |         if (file->name[0] != 0) |
|---|
| 296 | Â Â Â Â Â Â Â Â Â Â Â Â sc_asn1_put_tag(0x84, (u8 *) file->name, file->namelen, p, *outlen - (p - out), &p); |
|---|
| 297 |         else { |
|---|
| 298 | Â Â Â Â Â Â Â Â Â Â Â Â buf[0] = (file->id >> 8) & 0xFF; |
|---|
| 299 | Â Â Â Â Â Â Â Â Â Â Â Â buf[1] = file->id & 0xFF; |
|---|
| 300 | Â Â Â Â Â Â Â Â Â Â Â Â sc_asn1_put_tag(0x84, buf, 2, p, *outlen - (p - out), &p); |
|---|
| 301 | Â Â Â Â Â Â Â Â } |
|---|
| 302 | Â Â Â Â } |
|---|
| 303 | |
|---|
| 304 | Â Â Â Â |
|---|
| 305 | Â Â Â Â memcpy(buf, file->sec_attr, file->sec_attr_len); |
|---|
| 306 | Â Â Â Â sc_asn1_put_tag(0x86, buf, file->sec_attr_len, p, *outlen - (p - out), &p); |
|---|
| 307 | |
|---|
| 308 | Â Â Â Â |
|---|
| 309 |     if (file->prop_attr_len) { |
|---|
| 310 | Â Â Â Â Â Â Â Â memcpy(buf, file->prop_attr, file->prop_attr_len); |
|---|
| 311 | Â Â Â Â Â Â Â Â sc_asn1_put_tag(0x8A, buf, file->prop_attr_len, p, *outlen - (p - out), &p); |
|---|
| 312 | Â Â Â Â } |
|---|
| 313 | |
|---|
| 314 | Â Â Â Â |
|---|
| 315 |     if (file->type == SC_FILE_TYPE_DF) { |
|---|
| 316 |         if (card->type == SC_CARD_TYPE_SETCOS_EID_V2_1) { |
|---|
| 317 |             pin_key_info = (const u8*)"\xC1\x04\x81\x82\x83\x84"; |
|---|
| 318 | Â Â Â Â Â Â Â Â Â Â Â Â len = 6; |
|---|
| 319 | Â Â Â Â Â Â Â Â } |
|---|
| 320 |         else if (card->type == SC_CARD_TYPE_SETCOS_EID_V2_0) { |
|---|
| 321 |             pin_key_info = (const u8*)"\xC1\x04\x81\x82"; |
|---|
| 322 | Â Â Â Â Â Â Â Â Â Â Â Â len = 4; |
|---|
| 323 | Â Â Â Â Â Â Â Â } |
|---|
| 324 |         else { |
|---|
| 325 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 326 | Â Â Â Â Â Â Â Â Â Â Â Â if(file->path.len == 2) |
|---|
| 327 |                 pin_key_info = (const u8*)"\xC1\x04\x81\x82\x83\x84\xC2\x00";  |
|---|
| 328 | Â Â Â Â Â Â Â Â Â Â Â Â else |
|---|
| 329 |                 pin_key_info = (const u8 *)"\xC1\x04\x01\x02\x03\x04\xC2\x00"; |
|---|
| 330 | Â Â Â Â Â Â Â Â Â Â Â Â len = 8; |
|---|
| 331 | Â Â Â Â Â Â Â Â } |
|---|
| 332 | Â Â Â Â Â Â Â Â sc_asn1_put_tag(0xA5, pin_key_info, len, p, *outlen - (p - out), &p); |
|---|
| 333 | Â Â Â Â } |
|---|
| 334 | |
|---|
| 335 | Â Â Â Â |
|---|
| 336 | Â Â Â Â out[1] = p - out - 2; |
|---|
| 337 | |
|---|
| 338 | Â Â Â Â *outlen = p - out; |
|---|
| 339 |     return 0; |
|---|
| 340 | } |
|---|
| 341 | |
|---|
| 342 | static int setcos_construct_fci(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen) |
|---|
| 343 | { |
|---|
| 344 |     if (card->type == SC_CARD_TYPE_SETCOS_44 || |
|---|
| 345 | Â Â Â Â Â Â card->type == SC_CARD_TYPE_SETCOS_NIDEL || |
|---|
| 346 | Â Â Â Â Â Â SETCOS_IS_EID_APPLET(card)) |
|---|
| 347 |         return setcos_construct_fci_44(card, file, out, outlen); |
|---|
| 348 | Â Â Â Â else |
|---|
| 349 |         return iso_ops->construct_fci(card, file, out, outlen); |
|---|
| 350 | } |
|---|
| 351 | |
|---|
| 352 | static u8 acl_to_byte(const sc_acl_entry_t *e) |
|---|
| 353 | { |
|---|
| 354 |     switch (e->method) { |
|---|
| 355 |     case SC_AC_NONE: |
|---|
| 356 |         return 0x00; |
|---|
| 357 |     case SC_AC_CHV: |
|---|
| 358 |         switch (e->key_ref) { |
|---|
| 359 |         case 1: |
|---|
| 360 |             return 0x01; |
|---|
| 361 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 362 |         case 2: |
|---|
| 363 |             return 0x02; |
|---|
| 364 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 365 | Â Â Â Â Â Â Â Â default: |
|---|
| 366 |             return 0x00; |
|---|
| 367 | Â Â Â Â Â Â Â Â } |
|---|
| 368 | Â Â Â Â Â Â Â Â break; |
|---|
| 369 |     case SC_AC_TERM: |
|---|
| 370 |         return 0x04; |
|---|
| 371 |     case SC_AC_NEVER: |
|---|
| 372 |         return 0x0F; |
|---|
| 373 | Â Â Â Â } |
|---|
| 374 |     return 0x00; |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | static unsigned int acl_to_byte_44(const struct sc_acl_entry *e, u8* p_bNumber) |
|---|
| 378 | { |
|---|
| 379 | Â Â Â Â |
|---|
| 380 |     if (e == (sc_acl_entry_t *) 1)      |
|---|
| 381 |         return SC_AC_NEVER; |
|---|
| 382 |     else if ((e == (sc_acl_entry_t *) 2) || |
|---|
| 383 | Â Â Â Â Â Â Â Â Â (e == (sc_acl_entry_t *) 3) ||Â |
|---|
| 384 | Â Â Â Â Â Â Â Â Â (e == (sc_acl_entry_t *) 0)) |
|---|
| 385 |         return SC_AC_NONE; |
|---|
| 386 | |
|---|
| 387 | Â Â Â Â |
|---|
| 388 | Â Â Â Â *p_bNumber = e->key_ref; |
|---|
| 389 | Â Â Â Â return(e->method); |
|---|
| 390 | } |
|---|
| 391 | |
|---|
| 392 | |
|---|
| 393 | |
|---|
| 394 | static int setcos_pin_index_44(int *pins, int len, int pin) |
|---|
| 395 | { |
|---|
| 396 |     int i; |
|---|
| 397 |     for (i = 0; i < len; i++) { |
|---|
| 398 |         if (pins[i] == pin) |
|---|
| 399 |             return i; |
|---|
| 400 |         if (pins[i] == -1) { |
|---|
| 401 | Â Â Â Â Â Â Â Â Â Â Â Â pins[i] = pin; |
|---|
| 402 |             return i; |
|---|
| 403 | Â Â Â Â Â Â Â Â } |
|---|
| 404 | Â Â Â Â } |
|---|
| 405 | Â Â Â Â assert(i != len); |
|---|
| 406 |     return 0; |
|---|
| 407 | } |
|---|
| 408 | |
|---|
| 409 | |
|---|
| 410 | |
|---|
| 411 | static int setcos_create_file_44(sc_card_t *card, sc_file_t *file) |
|---|
| 412 | { |
|---|
| 413 |     const u8 bFileStatus = file->status == SC_FILE_STATUS_CREATION ? |
|---|
| 414 | Â Â Â Â Â Â Â Â SETEC_LCSI_CREATE : SETEC_LCSI_ACTIVATED; |
|---|
| 415 | Â Â Â Â u8 bCommands_always = 0; |
|---|
| 416 |     int pins[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; |
|---|
| 417 | Â Â Â Â u8 bCommands_pin[sizeof(pins)/sizeof(pins[0])]; |
|---|
| 418 | Â Â Â Â u8 bCommands_key = 0; |
|---|
| 419 | Â Â Â Â u8 bNumber = 0; |
|---|
| 420 | Â Â Â Â u8 bKeyNumber = 0; |
|---|
| 421 |     unsigned int bMethod = 0; |
|---|
| 422 | |
|---|
| 423 | Â Â Â Â |
|---|
| 424 |     const int df_idx[8] = { |
|---|
| 425 | Â Â Â Â Â Â Â Â SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE, |
|---|
| 426 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 427 | Â Â Â Â Â Â Â Â SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1}; |
|---|
| 428 |     const int ef_idx[8] = { |
|---|
| 429 | Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE, |
|---|
| 430 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 431 | Â Â Â Â Â Â Â Â -1, SC_AC_OP_ERASE, -1}; |
|---|
| 432 |     const int efi_idx[8] = { |
|---|
| 433 | Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE, |
|---|
| 434 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 435 | Â Â Â Â Â Â Â Â -1, SC_AC_OP_ERASE, -1}; |
|---|
| 436 | |
|---|
| 437 | Â Â Â Â |
|---|
| 438 | Â Â Â Â sc_file_set_prop_attr(file, &bFileStatus, 1); |
|---|
| 439 | |
|---|
| 440 | Â Â Â Â |
|---|
| 441 |     if (file->sec_attr_len == 0) { |
|---|
| 442 |         const int* p_idx; |
|---|
| 443 |         int      i; |
|---|
| 444 |         int      len = 0; |
|---|
| 445 | Â Â Â Â Â Â Â Â u8Â Â Â Â Â bBuf[32]; |
|---|
| 446 | |
|---|
| 447 | Â Â Â Â Â Â Â Â |
|---|
| 448 |         switch (file->type){ |
|---|
| 449 |         case SC_FILE_TYPE_DF:      |
|---|
| 450 | Â Â Â Â Â Â Â Â Â Â Â Â p_idx = df_idx; |
|---|
| 451 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 452 |         case SC_FILE_TYPE_INTERNAL_EF: |
|---|
| 453 | Â Â Â Â Â Â Â Â Â Â Â Â p_idx = efi_idx; |
|---|
| 454 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 455 | Â Â Â Â Â Â Â Â default:Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 456 | Â Â Â Â Â Â Â Â Â Â Â Â p_idx = ef_idx; |
|---|
| 457 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 458 | Â Â Â Â Â Â Â Â } |
|---|
| 459 | |
|---|
| 460 | Â Â Â Â Â Â Â Â |
|---|
| 461 | Â Â Â Â Â Â Â Â memset(bCommands_pin, 0, sizeof(bCommands_pin)); |
|---|
| 462 |         for (i = 7; i >= 0; i--) { |
|---|
| 463 | Â Â Â Â Â Â Â Â Â Â Â Â bCommands_always <<= 1; |
|---|
| 464 | Â Â Â Â Â Â Â Â Â Â Â Â bCommands_key <<= 1; |
|---|
| 465 | |
|---|
| 466 |             if (p_idx[i] == -1) |
|---|
| 467 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â continue; |
|---|
| 468 | |
|---|
| 469 | Â Â Â Â Â Â Â Â Â Â Â Â bMethod = acl_to_byte_44(file->acl[ p_idx[i] ], &bNumber); |
|---|
| 470 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 471 | Â Â Â Â Â Â Â Â Â Â Â Â switch(bMethod){ |
|---|
| 472 |             case SC_AC_NONE:            |
|---|
| 473 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bCommands_always |= 1; |
|---|
| 474 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 475 |             case SC_AC_CHV:             |
|---|
| 476 |                 if ((bNumber & 0x7F) == 0 || (bNumber & 0x7F) > 7) { |
|---|
| 477 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sc_error(card->ctx, "SetCOS 4.4 PIN refs can only be 1..7\n"); |
|---|
| 478 |                     return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 479 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 480 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bCommands_pin[setcos_pin_index_44(pins, sizeof(pins), (int) bNumber)] |= 1 << i; |
|---|
| 481 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 482 |             case SC_AC_TERM:            |
|---|
| 483 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bKeyNumber = bNumber;Â Â |
|---|
| 484 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bCommands_key |= 1; |
|---|
| 485 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 486 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 487 | Â Â Â Â Â Â Â Â } |
|---|
| 488 | |
|---|
| 489 | Â Â Â Â Â Â Â Â |
|---|
| 490 |         if (bCommands_always) { |
|---|
| 491 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 1; |
|---|
| 492 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = bCommands_always; |
|---|
| 493 | Â Â Â Â Â Â Â Â } |
|---|
| 494 | Â Â Â Â Â Â Â Â |
|---|
| 495 |         for (i = 0; i < (int)sizeof(bCommands_pin) && pins[i] != -1; i++) { |
|---|
| 496 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 2; |
|---|
| 497 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = bCommands_pin[i]; |
|---|
| 498 |             if (SETCOS_IS_EID_APPLET(card)) |
|---|
| 499 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = pins[i];Â |
|---|
| 500 | Â Â Â Â Â Â Â Â Â Â Â Â else |
|---|
| 501 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = pins[i] & 0x07;Â |
|---|
| 502 | Â Â Â Â Â Â Â Â } |
|---|
| 503 | Â Â Â Â Â Â Â Â |
|---|
| 504 |         if (bCommands_key) { |
|---|
| 505 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 2 | 0x20;Â Â Â Â Â Â Â Â Â |
|---|
| 506 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = bCommands_key; |
|---|
| 507 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = bKeyNumber; |
|---|
| 508 | Â Â Â Â Â Â Â Â } |
|---|
| 509 | Â Â Â Â Â Â Â Â |
|---|
| 510 | |
|---|
| 511 | Â Â Â Â Â Â Â Â bKeyNumber = 0; |
|---|
| 512 |         if ( (file->type == SC_FILE_TYPE_INTERNAL_EF) && |
|---|
| 513 | Â Â Â Â Â Â Â Â Â Â Â (acl_to_byte_44(file->acl[SC_AC_OP_CRYPTO], &bNumber) == SC_AC_CHV) ) { |
|---|
| 514 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 0x83; |
|---|
| 515 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 0x01; |
|---|
| 516 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = 0x2A;Â |
|---|
| 517 | Â Â Â Â Â Â Â Â Â Â Â Â bBuf[len++] = bNumber & 0x07;Â |
|---|
| 518 | Â Â Â Â Â Â Â Â } |
|---|
| 519 | |
|---|
| 520 | Â Â Â Â Â Â Â Â sc_file_set_sec_attr(file, bBuf, len); |
|---|
| 521 | Â Â Â Â } |
|---|
| 522 | |
|---|
| 523 |     return iso_ops->create_file(card, file); |
|---|
| 524 | } |
|---|
| 525 | |
|---|
| 526 | static int setcos_create_file(sc_card_t *card, sc_file_t *file) |
|---|
| 527 | { |
|---|
| 528 |     if (card->type == SC_CARD_TYPE_SETCOS_44 || SETCOS_IS_EID_APPLET(card)) |
|---|
| 529 |         return setcos_create_file_44(card, file); |
|---|
| 530 | |
|---|
| 531 |     if (file->prop_attr_len == 0) |
|---|
| 532 |         sc_file_set_prop_attr(file, (const u8 *) "\x03\x00\x00", 3); |
|---|
| 533 |     if (file->sec_attr_len == 0) { |
|---|
| 534 |         int idx[6], i; |
|---|
| 535 | Â Â Â Â Â Â Â Â u8 buf[6]; |
|---|
| 536 | |
|---|
| 537 |         if (file->type == SC_FILE_TYPE_DF) { |
|---|
| 538 |             const int df_idx[6] = { |
|---|
| 539 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE, |
|---|
| 540 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE, |
|---|
| 541 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE |
|---|
| 542 | Â Â Â Â Â Â Â Â Â Â Â Â }; |
|---|
| 543 |             for (i = 0; i < 6; i++) |
|---|
| 544 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â idx[i] = df_idx[i]; |
|---|
| 545 |         } else { |
|---|
| 546 |             const int ef_idx[6] = { |
|---|
| 547 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE, |
|---|
| 548 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE, |
|---|
| 549 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE |
|---|
| 550 | Â Â Â Â Â Â Â Â Â Â Â Â }; |
|---|
| 551 |             for (i = 0; i < 6; i++) |
|---|
| 552 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â idx[i] = ef_idx[i]; |
|---|
| 553 | Â Â Â Â Â Â Â Â } |
|---|
| 554 |         for (i = 0; i < 6; i++) { |
|---|
| 555 |             const struct sc_acl_entry *entry; |
|---|
| 556 | Â Â Â Â Â Â Â Â Â Â Â Â entry = sc_file_get_acl_entry(file, idx[i]); |
|---|
| 557 | Â Â Â Â Â Â Â Â Â Â Â Â buf[i] = acl_to_byte(entry); |
|---|
| 558 | Â Â Â Â Â Â Â Â } |
|---|
| 559 | |
|---|
| 560 | Â Â Â Â Â Â Â Â sc_file_set_sec_attr(file, buf, 6); |
|---|
| 561 | Â Â Â Â } |
|---|
| 562 | |
|---|
| 563 |     return iso_ops->create_file(card, file); |
|---|
| 564 | } |
|---|
| 565 | |
|---|
| 566 | static int setcos_set_security_env2(sc_card_t *card, |
|---|
| 567 |                   const sc_security_env_t *env, int se_num) |
|---|
| 568 | { |
|---|
| 569 | Â Â Â Â sc_apdu_t apdu; |
|---|
| 570 | Â Â Â Â u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
|---|
| 571 | Â Â Â Â u8 *p; |
|---|
| 572 |     int r, locked = 0; |
|---|
| 573 | |
|---|
| 574 | Â Â Â Â assert(card != NULL && env != NULL); |
|---|
| 575 | |
|---|
| 576 |     if (card->type == SC_CARD_TYPE_SETCOS_44 || |
|---|
| 577 | Â Â Â Â Â Â card->type == SC_CARD_TYPE_SETCOS_NIDEL || |
|---|
| 578 | Â Â Â Â Â Â SETCOS_IS_EID_APPLET(card)) { |
|---|
| 579 |         if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) { |
|---|
| 580 | Â Â Â Â Â Â Â Â Â Â Â Â sc_error(card->ctx, "asymmetric keyref not supported.\n"); |
|---|
| 581 |             return SC_ERROR_NOT_SUPPORTED; |
|---|
| 582 | Â Â Â Â Â Â Â Â } |
|---|
| 583 |         if (se_num > 0) { |
|---|
| 584 | Â Â Â Â Â Â Â Â Â Â Â Â sc_error(card->ctx, "restore security environment not supported.\n"); |
|---|
| 585 |             return SC_ERROR_NOT_SUPPORTED; |
|---|
| 586 | Â Â Â Â Â Â Â Â } |
|---|
| 587 | Â Â Â Â } |
|---|
| 588 | |
|---|
| 589 | Â Â Â Â sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); |
|---|
| 590 |     switch (env->operation) { |
|---|
| 591 |     case SC_SEC_OPERATION_DECIPHER: |
|---|
| 592 | Â Â Â Â Â Â Â Â |
|---|
| 593 | Â Â Â Â Â Â Â Â apdu.p1 = 0x41; |
|---|
| 594 | Â Â Â Â Â Â Â Â apdu.p2 = 0xB8; |
|---|
| 595 | Â Â Â Â Â Â Â Â break; |
|---|
| 596 |     case SC_SEC_OPERATION_SIGN: |
|---|
| 597 | Â Â Â Â Â Â Â Â |
|---|
| 598 | Â Â Â Â Â Â Â Â apdu.p1 = ((card->type == SC_CARD_TYPE_SETCOS_FINEID_V2) || |
|---|
| 599 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â (card->type == SC_CARD_TYPE_SETCOS_44) || |
|---|
| 600 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â (card->type == SC_CARD_TYPE_SETCOS_NIDEL) || |
|---|
| 601 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â SETCOS_IS_EID_APPLET(card)) ? 0x41 : 0x81; |
|---|
| 602 | Â Â Â Â Â Â Â Â apdu.p2 = 0xB6; |
|---|
| 603 | Â Â Â Â Â Â Â Â break; |
|---|
| 604 | Â Â Â Â default: |
|---|
| 605 |         return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 606 | Â Â Â Â } |
|---|
| 607 | Â Â Â Â apdu.le = 0; |
|---|
| 608 | Â Â Â Â p = sbuf; |
|---|
| 609 |     if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) { |
|---|
| 610 | Â Â Â Â Â Â Â Â *p++ = 0x80;Â Â |
|---|
| 611 | Â Â Â Â Â Â Â Â *p++ = 0x01; |
|---|
| 612 | Â Â Â Â Â Â Â Â *p++ = env->algorithm_ref & 0xFF; |
|---|
| 613 | Â Â Â Â } |
|---|
| 614 |     if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) { |
|---|
| 615 | Â Â Â Â Â Â Â Â *p++ = 0x81; |
|---|
| 616 | Â Â Â Â Â Â Â Â *p++ = env->file_ref.len; |
|---|
| 617 | Â Â Â Â Â Â Â Â memcpy(p, env->file_ref.value, env->file_ref.len); |
|---|
| 618 | Â Â Â Â Â Â Â Â p += env->file_ref.len; |
|---|
| 619 | Â Â Â Â } |
|---|
| 620 |     if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { |
|---|
| 621 |         if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) |
|---|
| 622 | Â Â Â Â Â Â Â Â Â Â Â Â *p++ = 0x83; |
|---|
| 623 | Â Â Â Â Â Â Â Â else |
|---|
| 624 | Â Â Â Â Â Â Â Â Â Â Â Â *p++ = 0x84; |
|---|
| 625 | Â Â Â Â Â Â Â Â *p++ = env->key_ref_len; |
|---|
| 626 | Â Â Â Â Â Â Â Â memcpy(p, env->key_ref, env->key_ref_len); |
|---|
| 627 | Â Â Â Â Â Â Â Â p += env->key_ref_len; |
|---|
| 628 | Â Â Â Â } |
|---|
| 629 | Â Â Â Â r = p - sbuf; |
|---|
| 630 | Â Â Â Â apdu.lc = r; |
|---|
| 631 | Â Â Â Â apdu.datalen = r; |
|---|
| 632 | Â Â Â Â apdu.data = sbuf; |
|---|
| 633 | Â Â Â Â apdu.resplen = 0; |
|---|
| 634 |     if (se_num > 0) { |
|---|
| 635 | Â Â Â Â Â Â Â Â r = sc_lock(card); |
|---|
| 636 | Â Â Â Â Â Â Â Â SC_TEST_RET(card->ctx, r, "sc_lock() failed"); |
|---|
| 637 | Â Â Â Â Â Â Â Â locked = 1; |
|---|
| 638 | Â Â Â Â } |
|---|
| 639 |     if (apdu.datalen != 0) { |
|---|
| 640 | Â Â Â Â Â Â Â Â r = sc_transmit_apdu(card, &apdu); |
|---|
| 641 |         if (r) { |
|---|
| 642 | Â Â Â Â Â Â Â Â Â Â Â Â sc_perror(card->ctx, r, "APDU transmit failed"); |
|---|
| 643 |             goto err; |
|---|
| 644 | Â Â Â Â Â Â Â Â } |
|---|
| 645 | Â Â Â Â Â Â Â Â r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
|---|
| 646 |         if (r) { |
|---|
| 647 | Â Â Â Â Â Â Â Â Â Â Â Â sc_perror(card->ctx, r, "Card returned error"); |
|---|
| 648 |             goto err; |
|---|
| 649 | Â Â Â Â Â Â Â Â } |
|---|
| 650 | Â Â Â Â } |
|---|
| 651 |     if (se_num <= 0) |
|---|
| 652 |         return 0; |
|---|
| 653 | Â Â Â Â sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num); |
|---|
| 654 | Â Â Â Â r = sc_transmit_apdu(card, &apdu); |
|---|
| 655 | Â Â Â Â sc_unlock(card); |
|---|
| 656 | Â Â Â Â SC_TEST_RET(card->ctx, r, "APDU transmit failed"); |
|---|
| 657 |     return sc_check_sw(card, apdu.sw1, apdu.sw2); |
|---|
| 658 | err: |
|---|
| 659 |     if (locked) |
|---|
| 660 | Â Â Â Â Â Â Â Â sc_unlock(card); |
|---|
| 661 |     return r; |
|---|
| 662 | } |
|---|
| 663 | |
|---|
| 664 | static int setcos_set_security_env(sc_card_t *card, |
|---|
| 665 |                   const sc_security_env_t *env, int se_num) |
|---|
| 666 | { |
|---|
| 667 |     if (env->flags & SC_SEC_ENV_ALG_PRESENT) { |
|---|
| 668 | Â Â Â Â Â Â Â Â sc_security_env_t tmp; |
|---|
| 669 | |
|---|
| 670 | Â Â Â Â Â Â Â Â tmp = *env; |
|---|
| 671 | Â Â Â Â Â Â Â Â tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT; |
|---|
| 672 | Â Â Â Â Â Â Â Â tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT; |
|---|
| 673 |         if (tmp.algorithm != SC_ALGORITHM_RSA) { |
|---|
| 674 | Â Â Â Â Â Â Â Â Â Â Â Â sc_error(card->ctx, "Only RSA algorithm supported.\n"); |
|---|
| 675 |             return SC_ERROR_NOT_SUPPORTED; |
|---|
| 676 | Â Â Â Â Â Â Â Â } |
|---|
| 677 |         switch (card->type) { |
|---|
| 678 |         case SC_CARD_TYPE_SETCOS_PKI: |
|---|
| 679 |         case SC_CARD_TYPE_SETCOS_FINEID: |
|---|
| 680 |         case SC_CARD_TYPE_SETCOS_FINEID_V2: |
|---|
| 681 |         case SC_CARD_TYPE_SETCOS_NIDEL: |
|---|
| 682 |         case SC_CARD_TYPE_SETCOS_44: |
|---|
| 683 |         case SC_CARD_TYPE_SETCOS_EID_V2_0: |
|---|
| 684 |         case SC_CARD_TYPE_SETCOS_EID_V2_1: |
|---|
| 685 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 686 | Â Â Â Â Â Â Â Â default: |
|---|
| 687 | Â Â Â Â Â Â Â Â Â Â Â Â sc_error(card->ctx, "Card does not support RSA.\n"); |
|---|
| 688 |             return SC_ERROR_NOT_SUPPORTED; |
|---|
| 689 | Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 690 | Â Â Â Â Â Â Â Â } |
|---|
| 691 | Â Â Â Â Â Â Â Â tmp.algorithm_ref = 0x00; |
|---|
| 692 | Â Â Â Â Â Â Â Â |
|---|
| 693 | |
|---|
| 694 | |
|---|
| 695 |         if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) |
|---|
| 696 | Â Â Â Â Â Â Â Â Â Â Â Â tmp.algorithm_ref = 0x02; |
|---|
| 697 |         if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) |
|---|
| 698 | Â Â Â Â Â Â Â Â Â Â Â Â tmp.algorithm_ref |= 0x10; |
|---|
| 699 |         return setcos_set_security_env2(card, &tmp, se_num); |
|---|
| 700 | Â Â Â Â } |
|---|
| 701 |     return setcos_set_security_env2(card, env, se_num); |
|---|
| 702 | } |
|---|
| 703 | |
|---|
| 704 | static void add_acl_entry(sc_file_t *file, int op, u8 byte) |
|---|
| 705 | { |
|---|
| 706 |     unsigned int method, key_ref = SC_AC_KEY_REF_NONE; |
|---|
| 707 | |
|---|
| 708 |     switch (byte >> 4) { |
|---|
| 709 |     case 0: |
|---|
| 710 | Â Â Â Â Â Â Â Â method = SC_AC_NONE; |
|---|
| 711 | Â Â Â Â Â Â Â Â break; |
|---|
| 712 |     case 1: |
|---|
| 713 | Â Â Â Â Â Â Â Â method = SC_AC_CHV; |
|---|
| 714 | Â Â Â Â Â Â Â Â key_ref = 1; |
|---|
| 715 | Â Â Â Â Â Â Â Â break; |
|---|
| 716 |     case 2: |
|---|
| 717 | Â Â Â Â Â Â Â Â method = SC_AC_CHV; |
|---|
| 718 | Â Â Â Â Â Â Â Â key_ref = 2; |
|---|
| 719 | Â Â Â Â Â Â Â Â break; |
|---|
| 720 |     case 4: |
|---|
| 721 | Â Â Â Â Â Â Â Â method = SC_AC_TERM; |
|---|
| 722 | Â Â Â Â Â Â Â Â break; |
|---|
| 723 |     case 15: |
|---|
| 724 | Â Â Â Â Â Â Â Â method = SC_AC_NEVER; |
|---|
| 725 | Â Â Â Â Â Â Â Â break; |
|---|
| 726 | Â Â Â Â default: |
|---|
| 727 | Â Â Â Â Â Â Â Â method = SC_AC_UNKNOWN; |
|---|
| 728 | Â Â Â Â Â Â Â Â break; |
|---|
| 729 | Â Â Â Â } |
|---|
| 730 | Â Â Â Â sc_file_add_acl_entry(file, op, method, key_ref); |
|---|
| 731 | } |
|---|
| 732 | |
|---|
| 733 | static void parse_sec_attr(sc_file_t *file, const u8 * buf, size_t len) |
|---|
| 734 | { |
|---|
| 735 |     int i; |
|---|
| 736 |     int idx[6]; |
|---|
| 737 | |
|---|
| 738 |     if (len < 6) |
|---|
| 739 | Â Â Â Â Â Â Â Â return; |
|---|
| 740 |     if (file->type == SC_FILE_TYPE_DF) { |
|---|
| 741 |         const int df_idx[6] = { |
|---|
| 742 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE, |
|---|
| 743 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE, |
|---|
| 744 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE |
|---|
| 745 | Â Â Â Â Â Â Â Â }; |
|---|
| 746 |         for (i = 0; i < 6; i++) |
|---|
| 747 | Â Â Â Â Â Â Â Â Â Â Â Â idx[i] = df_idx[i]; |
|---|
| 748 |     } else { |
|---|
| 749 |         const int ef_idx[6] = { |
|---|
| 750 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE, |
|---|
| 751 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE, |
|---|
| 752 | Â Â Â Â Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE |
|---|
| 753 | Â Â Â Â Â Â Â Â }; |
|---|
| 754 |         for (i = 0; i < 6; i++) |
|---|
| 755 | Â Â Â Â Â Â Â Â Â Â Â Â idx[i] = ef_idx[i]; |
|---|
| 756 | Â Â Â Â } |
|---|
| 757 |     for (i = 0; i < 6; i++) |
|---|
| 758 | Â Â Â Â Â Â Â Â add_acl_entry(file, idx[i], buf[i]); |
|---|
| 759 | } |
|---|
| 760 | |
|---|
| 761 | static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len) |
|---|
| 762 | { |
|---|
| 763 | Â Â Â Â |
|---|
| 764 |     const int df_idx[8] = { |
|---|
| 765 | Â Â Â Â Â Â Â Â SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE, |
|---|
| 766 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 767 | Â Â Â Â Â Â Â Â SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1}; |
|---|
| 768 |     const int ef_idx[8] = { |
|---|
| 769 | Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE, |
|---|
| 770 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 771 | Â Â Â Â Â Â Â Â -1, SC_AC_OP_ERASE, -1}; |
|---|
| 772 |     const int efi_idx[8] = { |
|---|
| 773 | Â Â Â Â Â Â Â Â SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE, |
|---|
| 774 | Â Â Â Â Â Â Â Â SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE, |
|---|
| 775 | Â Â Â Â Â Â Â Â -1, SC_AC_OP_ERASE, -1}; |
|---|
| 776 | |
|---|
| 777 | Â Â Â Â u8Â Â Â Â Â Â Â bValue; |
|---|
| 778 |     int       i; |
|---|
| 779 |     int       iKeyRef = 0; |
|---|
| 780 |     int       iMethod; |
|---|
| 781 |     int       iPinCount; |
|---|
| 782 |     int       iOffset = 0; |
|---|
| 783 |     int       iOperation; |
|---|
| 784 |     const int*   p_idx; |
|---|
| 785 | |
|---|
| 786 | Â Â Â Â |
|---|
| 787 |     while (len > 1) {                |
|---|
| 788 |         int   iACLen  = buf[iOffset] & 0x0F; |
|---|
| 789 | |
|---|
| 790 | Â Â Â Â Â Â Â Â iPinCount = -1;Â Â Â Â Â Â Â Â Â |
|---|
| 791 | Â Â Â Â Â Â Â Â iMethod = SC_AC_NONE;Â Â Â Â Â Â |
|---|
| 792 | |
|---|
| 793 |         if (buf[iOffset] & 0X80) { |
|---|
| 794 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 795 |             int   iParmLen = 1;          |
|---|
| 796 |             int   iKeyLen = 0;          |
|---|
| 797 | |
|---|
| 798 |             if (buf[iOffset]  & 0x20) iKeyLen++; |
|---|
| 799 |             if (buf[iOffset+1] & 0x40) iParmLen++; |
|---|
| 800 |             if (buf[iOffset+1] & 0x20) iParmLen++; |
|---|
| 801 |             if (buf[iOffset+1] & 0x10) iParmLen++; |
|---|
| 802 |             if (buf[iOffset+1] & 0x08) iParmLen++; |
|---|
| 803 | |
|---|
| 804 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 805 | Â Â Â Â Â Â Â Â Â Â Â Â if(iKeyLen) { |
|---|
| 806 |                 int iSC = buf[iOffset+iACLen]; |
|---|
| 807 | |
|---|
| 808 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â switch( (iSC>>5) & 0x03 ){ |
|---|
| 809 |                 case 0: |
|---|
| 810 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_TERM;Â Â Â Â Â Â |
|---|
| 811 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 812 |                 case 1: |
|---|
| 813 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_AUT;Â Â Â Â Â Â |
|---|
| 814 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 815 |                 case 2: |
|---|
| 816 |                 case 3: |
|---|
| 817 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_PRO;Â Â Â Â Â Â |
|---|
| 818 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 819 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 820 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iKeyRef = iSC & 0x1F;Â Â Â Â Â Â Â Â Â Â |
|---|
| 821 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 822 | |
|---|
| 823 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 824 |             if (iACLen > (1+iParmLen+iKeyLen)) { |
|---|
| 825 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iKeyRef = buf[iOffset+1+1+iParmLen];Â |
|---|
| 826 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_CHV; |
|---|
| 827 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 828 | |
|---|
| 829 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 830 | Â Â Â Â Â Â Â Â Â Â Â Â switch(buf[iOffset+2]){ |
|---|
| 831 |             case 0x2A:           |
|---|
| 832 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iOperation = SC_AC_OP_CRYPTO; |
|---|
| 833 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 834 |             case 0x46:           |
|---|
| 835 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iOperation = SC_AC_OP_UPDATE; |
|---|
| 836 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 837 | Â Â Â Â Â Â Â Â Â Â Â Â default: |
|---|
| 838 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iOperation = SC_AC_OP_SELECT; |
|---|
| 839 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 840 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 841 | Â Â Â Â Â Â Â Â Â Â Â Â sc_file_add_acl_entry(file, iOperation, iMethod, iKeyRef); |
|---|
| 842 | Â Â Â Â Â Â Â Â } |
|---|
| 843 |         else { |
|---|
| 844 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 845 | |
|---|
| 846 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 847 |             switch (file->type) { |
|---|
| 848 |             case SC_FILE_TYPE_DF:      |
|---|
| 849 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â p_idx = df_idx; |
|---|
| 850 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 851 |             case SC_FILE_TYPE_INTERNAL_EF:  |
|---|
| 852 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â p_idx = efi_idx; |
|---|
| 853 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 854 | Â Â Â Â Â Â Â Â Â Â Â Â default:Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 855 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â p_idx = ef_idx; |
|---|
| 856 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 857 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 858 | |
|---|
| 859 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 860 | Â Â Â Â Â Â Â Â Â Â Â Â iPinCount = iACLen - 1;Â Â Â Â Â |
|---|
| 861 | |
|---|
| 862 |             if (buf[iOffset] & 0x20) { |
|---|
| 863 |                 int iSC = buf[iOffset + iACLen]; |
|---|
| 864 | |
|---|
| 865 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â switch( (iSC>>5) & 0x03 ) { |
|---|
| 866 |                 case 0: |
|---|
| 867 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_TERM;Â Â Â Â Â Â |
|---|
| 868 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 869 |                 case 1: |
|---|
| 870 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_AUT;Â Â Â Â Â Â |
|---|
| 871 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 872 |                 case 2: |
|---|
| 873 |                 case 3: |
|---|
| 874 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iMethod = SC_AC_PRO;Â Â Â Â Â Â |
|---|
| 875 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break; |
|---|
| 876 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 877 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iKeyRef = iSC & 0x1F;Â Â Â Â Â Â Â Â Â Â |
|---|
| 878 | |
|---|
| 879 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iPinCount--;Â Â Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 880 | Â Â Â Â Â Â Â Â Â Â Â Â } |
|---|
| 881 | |
|---|
| 882 | Â Â Â Â Â Â Â Â Â Â Â Â |
|---|
| 883 |             if ( iPinCount > 0 ) { |
|---|
| 884 | Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iKeyRef = buf[iOffset + 2];Â Â Â |
|---|
| 885 | Â Â Â Â Â Â Â Â |
|---|