| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | #include "internal.h" |
|---|
| 22 | #include "pkcs15.h" |
|---|
| 23 | #include "asn1.h" |
|---|
| 24 | #include <assert.h> |
|---|
| 25 | #include <string.h> |
|---|
| 26 | #include <stdlib.h> |
|---|
| 27 | #include <stdio.h> |
|---|
| 28 | |
|---|
| 29 | static const struct sc_asn1_entry c_asn1_com_ao_attr[] = { |
|---|
| 30 | { "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL }, |
|---|
| 31 | { NULL, 0, 0, 0, NULL, NULL } |
|---|
| 32 | }; |
|---|
| 33 | static const struct sc_asn1_entry c_asn1_pin_attr[] = { |
|---|
| 34 | { "pinFlags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, |
|---|
| 35 | { "pinType", SC_ASN1_ENUMERATED, SC_ASN1_TAG_ENUMERATED, 0, NULL, NULL }, |
|---|
| 36 | { "minLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, |
|---|
| 37 | { "storedLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, |
|---|
| 38 | { "maxLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
|---|
| 39 | { "pinReference", SC_ASN1_INTEGER, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL, NULL }, |
|---|
| 40 | { "padChar", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
|---|
| 41 | { "lastPinChange",SC_ASN1_GENERALIZEDTIME, SC_ASN1_TAG_GENERALIZEDTIME, SC_ASN1_OPTIONAL, NULL, NULL }, |
|---|
| 42 | { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
|---|
| 43 | { NULL, 0, 0, 0, NULL, NULL } |
|---|
| 44 | }; |
|---|
| 45 | static const struct sc_asn1_entry c_asn1_type_pin_attr[] = { |
|---|
| 46 | { "pinAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
|---|
| 47 | { NULL, 0, 0, 0, NULL, NULL } |
|---|
| 48 | }; |
|---|
| 49 | static const struct sc_asn1_entry c_asn1_pin[] = { |
|---|
| 50 | { "pin", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
|---|
| 51 | { NULL, 0, 0, 0, NULL, NULL } |
|---|
| 52 | }; |
|---|
| 53 | |
|---|
| 54 | int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, |
|---|
| 55 | struct sc_pkcs15_object *obj, |
|---|
| 56 | const u8 ** buf, size_t *buflen) |
|---|
| 57 | { |
|---|
| 58 | sc_context_t *ctx = p15card->card->ctx; |
|---|
| 59 | struct sc_pkcs15_pin_info info; |
|---|
| 60 | int r; |
|---|
| 61 | size_t flags_len = sizeof(info.flags); |
|---|
| 62 | size_t padchar_len = 1; |
|---|
| 63 | struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; |
|---|
| 64 | struct sc_asn1_entry asn1_pin[2]; |
|---|
| 65 | struct sc_asn1_pkcs15_object pin_obj = { obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; |
|---|
| 66 | |
|---|
| 67 | sc_copy_asn1_entry(c_asn1_pin, asn1_pin); |
|---|
| 68 | sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr); |
|---|
| 69 | sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr); |
|---|
| 70 | sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr); |
|---|
| 71 | |
|---|
| 72 | sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 0); |
|---|
| 73 | |
|---|
| 74 | sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 0); |
|---|
| 75 | |
|---|
| 76 | sc_format_asn1_entry(asn1_pin_attr + 0, &info.flags, &flags_len, 0); |
|---|
| 77 | sc_format_asn1_entry(asn1_pin_attr + 1, &info.type, NULL, 0); |
|---|
| 78 | sc_format_asn1_entry(asn1_pin_attr + 2, &info.min_length, NULL, 0); |
|---|
| 79 | sc_format_asn1_entry(asn1_pin_attr + 3, &info.stored_length, NULL, 0); |
|---|
| 80 | sc_format_asn1_entry(asn1_pin_attr + 4, &info.max_length, NULL, 0); |
|---|
| 81 | sc_format_asn1_entry(asn1_pin_attr + 5, &info.reference, NULL, 0); |
|---|
| 82 | sc_format_asn1_entry(asn1_pin_attr + 6, &info.pad_char, &padchar_len, 0); |
|---|
| 83 | |
|---|
| 84 | sc_format_asn1_entry(asn1_pin_attr + 8, &info.path, NULL, 0); |
|---|
| 85 | |
|---|
| 86 | sc_format_asn1_entry(asn1_com_ao_attr + 0, &info.auth_id, NULL, 0); |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | memset(&info, 0, sizeof(info)); |
|---|
| 90 | info.reference = 0; |
|---|
| 91 | info.tries_left = -1; |
|---|
| 92 | |
|---|
| 93 | r = sc_asn1_decode(ctx, asn1_pin, *buf, *buflen, buf, buflen); |
|---|
| 94 | if (r == SC_ERROR_ASN1_END_OF_CONTENTS) |
|---|
| 95 | return r; |
|---|
| 96 | SC_TEST_RET(ctx, r, "ASN.1 decoding failed"); |
|---|
| 97 | info.magic = SC_PKCS15_PIN_MAGIC; |
|---|
| 98 | obj->type = SC_PKCS15_TYPE_AUTH_PIN; |
|---|
| 99 | obj->data = malloc(sizeof(info)); |
|---|
| 100 | if (obj->data == NULL) |
|---|
| 101 | SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); |
|---|
| 102 | if (info.max_length == 0) { |
|---|
| 103 | if (p15card->card->max_pin_len != 0) |
|---|
| 104 | info.max_length = p15card->card->max_pin_len; |
|---|
| 105 | else if (info.stored_length != 0) |
|---|
| 106 | info.max_length = info.type != SC_PKCS15_PIN_TYPE_BCD ? |
|---|
| 107 | info.stored_length : 2 * info.stored_length; |
|---|
| 108 | else |
|---|
| 109 | info.max_length = 8; |
|---|
| 110 | } |
|---|
| 111 | memcpy(obj->data, &info, sizeof(info)); |
|---|
| 112 | |
|---|
| 113 | return 0; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx, |
|---|
| 117 | const struct sc_pkcs15_object *obj, |
|---|
| 118 | u8 **buf, size_t *buflen) |
|---|
| 119 | { |
|---|
| 120 | struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; |
|---|
| 121 | struct sc_asn1_entry asn1_pin[2]; |
|---|
| 122 | struct sc_pkcs15_pin_info *pin = |
|---|
| 123 | (struct sc_pkcs15_pin_info *) obj->data; |
|---|
| 124 | struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj, |
|---|
| 125 | asn1_com_ao_attr, NULL, asn1_type_pin_attr }; |
|---|
| 126 | int r; |
|---|
| 127 | size_t flags_len; |
|---|
| 128 | size_t padchar_len = 1; |
|---|
| 129 | |
|---|
| 130 | sc_copy_asn1_entry(c_asn1_pin, asn1_pin); |
|---|
| 131 | sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr); |
|---|
| 132 | sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr); |
|---|
| 133 | sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr); |
|---|
| 134 | |
|---|
| 135 | sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 1); |
|---|
| 136 | |
|---|
| 137 | sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1); |
|---|
| 138 | |
|---|
| 139 | flags_len = sizeof(pin->flags); |
|---|
| 140 | sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 1); |
|---|
| 141 | sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 1); |
|---|
| 142 | sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 1); |
|---|
| 143 | sc_format_asn1_entry(asn1_pin_attr + 3, &pin->stored_length, NULL, 1); |
|---|
| 144 | if (pin->max_length > 0) |
|---|
| 145 | sc_format_asn1_entry(asn1_pin_attr + 4, &pin->max_length, NULL, 1); |
|---|
| 146 | if (pin->reference >= 0) |
|---|
| 147 | sc_format_asn1_entry(asn1_pin_attr + 5, &pin->reference, NULL, 1); |
|---|
| 148 | |
|---|
| 149 | sc_format_asn1_entry(asn1_pin_attr + 6, &pin->pad_char, &padchar_len, 1); |
|---|
| 150 | sc_format_asn1_entry(asn1_pin_attr + 8, &pin->path, NULL, 1); |
|---|
| 151 | |
|---|
| 152 | sc_format_asn1_entry(asn1_com_ao_attr + 0, &pin->auth_id, NULL, 1); |
|---|
| 153 | |
|---|
| 154 | assert(pin->magic == SC_PKCS15_PIN_MAGIC); |
|---|
| 155 | r = sc_asn1_encode(ctx, asn1_pin, buf, buflen); |
|---|
| 156 | |
|---|
| 157 | return r; |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | static int _validate_pin(struct sc_pkcs15_card *p15card, |
|---|
| 161 | struct sc_pkcs15_pin_info *pin, |
|---|
| 162 | size_t pinlen) |
|---|
| 163 | { |
|---|
| 164 | size_t max_length; |
|---|
| 165 | assert(p15card != NULL); |
|---|
| 166 | |
|---|
| 167 | if (pin->magic != SC_PKCS15_PIN_MAGIC) |
|---|
| 168 | return SC_ERROR_OBJECT_NOT_VALID; |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | if (pin->stored_length > SC_MAX_PIN_SIZE) |
|---|
| 172 | return SC_ERROR_BUFFER_TOO_SMALL; |
|---|
| 173 | |
|---|
| 174 | |
|---|
| 175 | if (p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) |
|---|
| 176 | return SC_SUCCESS; |
|---|
| 177 | |
|---|
| 178 | |
|---|
| 179 | max_length = pin->max_length != 0 ? pin->max_length : SC_MAX_PIN_SIZE; |
|---|
| 180 | if (pinlen > max_length || pinlen < pin->min_length) |
|---|
| 181 | return SC_ERROR_INVALID_PIN_LENGTH; |
|---|
| 182 | |
|---|
| 183 | return SC_SUCCESS; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | |
|---|
| 187 | |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, |
|---|
| 194 | struct sc_pkcs15_pin_info *pin, |
|---|
| 195 | const u8 *pincode, size_t pinlen) |
|---|
| 196 | { |
|---|
| 197 | int r; |
|---|
| 198 | sc_card_t *card; |
|---|
| 199 | struct sc_pin_cmd_data data; |
|---|
| 200 | |
|---|
| 201 | if ((r = _validate_pin(p15card, pin, pinlen)) != SC_SUCCESS) |
|---|
| 202 | return r; |
|---|
| 203 | |
|---|
| 204 | card = p15card->card; |
|---|
| 205 | |
|---|
| 206 | r = sc_lock(card); |
|---|
| 207 | if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) { |
|---|
| 208 | r = sc_lock(card); |
|---|
| 209 | } |
|---|
| 210 | SC_TEST_RET(card->ctx, r, "sc_lock() failed"); |
|---|
| 211 | |
|---|
| 212 | if (pin->path.len > 0) { |
|---|
| 213 | r = sc_select_file(card, &pin->path, NULL); |
|---|
| 214 | if (r) |
|---|
| 215 | goto out; |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | memset(&data, 0, sizeof(data)); |
|---|
| 220 | data.cmd = SC_PIN_CMD_VERIFY; |
|---|
| 221 | data.pin_type = SC_AC_CHV; |
|---|
| 222 | data.pin_reference = pin->reference; |
|---|
| 223 | data.pin1.min_length = pin->min_length; |
|---|
| 224 | data.pin1.max_length = pin->max_length; |
|---|
| 225 | data.pin1.pad_length = pin->stored_length; |
|---|
| 226 | data.pin1.pad_char = pin->pad_char; |
|---|
| 227 | data.pin1.data = pincode; |
|---|
| 228 | data.pin1.len = pinlen; |
|---|
| 229 | |
|---|
| 230 | if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) |
|---|
| 231 | data.flags |= SC_PIN_CMD_NEED_PADDING; |
|---|
| 232 | |
|---|
| 233 | switch (pin->type) { |
|---|
| 234 | case SC_PKCS15_PIN_TYPE_BCD: |
|---|
| 235 | data.pin1.encoding = SC_PIN_ENCODING_BCD; |
|---|
| 236 | break; |
|---|
| 237 | case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: |
|---|
| 238 | data.pin1.encoding = SC_PIN_ENCODING_ASCII; |
|---|
| 239 | break; |
|---|
| 240 | default: |
|---|
| 241 | |
|---|
| 242 | data.pin1.encoding = 0; |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { |
|---|
| 246 | data.flags |= SC_PIN_CMD_USE_PINPAD; |
|---|
| 247 | if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN) |
|---|
| 248 | data.pin1.prompt = "Please enter SO PIN"; |
|---|
| 249 | else |
|---|
| 250 | data.pin1.prompt = "Please enter PIN"; |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | r = sc_pin_cmd(card, &data, &pin->tries_left); |
|---|
| 254 | out: |
|---|
| 255 | sc_unlock(card); |
|---|
| 256 | return r; |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | |
|---|
| 260 | |
|---|
| 261 | |
|---|
| 262 | int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, |
|---|
| 263 | struct sc_pkcs15_pin_info *pin, |
|---|
| 264 | const u8 *oldpin, size_t oldpinlen, |
|---|
| 265 | const u8 *newpin, size_t newpinlen) |
|---|
| 266 | { |
|---|
| 267 | int r; |
|---|
| 268 | sc_card_t *card; |
|---|
| 269 | struct sc_pin_cmd_data data; |
|---|
| 270 | |
|---|
| 271 | |
|---|
| 272 | if ((r = _validate_pin(p15card, pin, oldpinlen)) != SC_SUCCESS) |
|---|
| 273 | return r; |
|---|
| 274 | if ((r = _validate_pin(p15card, pin, newpinlen)) != SC_SUCCESS) |
|---|
| 275 | return r; |
|---|
| 276 | |
|---|
| 277 | card = p15card->card; |
|---|
| 278 | r = sc_lock(card); |
|---|
| 279 | SC_TEST_RET(card->ctx, r, "sc_lock() failed"); |
|---|
| 280 | |
|---|
| 281 | if (pin->path.len > 0) { |
|---|
| 282 | r = sc_select_file(card, &pin->path, NULL); |
|---|
| 283 | if (r) |
|---|
| 284 | goto out; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | |
|---|
| 288 | memset(&data, 0, sizeof(data)); |
|---|
| 289 | data.cmd = SC_PIN_CMD_CHANGE; |
|---|
| 290 | data.pin_type = SC_AC_CHV; |
|---|
| 291 | data.pin_reference = pin->reference; |
|---|
| 292 | data.pin1.data = oldpin; |
|---|
| 293 | data.pin1.len = oldpinlen; |
|---|
| 294 | data.pin1.pad_char = pin->pad_char; |
|---|
| 295 | data.pin1.min_length = pin->min_length; |
|---|
| 296 | data.pin1.max_length = pin->max_length; |
|---|
| 297 | data.pin1.pad_length = pin->stored_length; |
|---|
| 298 | data.pin2.data = newpin; |
|---|
| 299 | data.pin2.len = newpinlen; |
|---|
| 300 | data.pin2.pad_char = pin->pad_char; |
|---|
| 301 | data.pin2.min_length = pin->min_length; |
|---|
| 302 | data.pin2.max_length = pin->max_length; |
|---|
| 303 | data.pin2.pad_length = pin->stored_length; |
|---|
| 304 | |
|---|
| 305 | if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) |
|---|
| 306 | data.flags |= SC_PIN_CMD_NEED_PADDING; |
|---|
| 307 | |
|---|
| 308 | switch (pin->type) { |
|---|
| 309 | case SC_PKCS15_PIN_TYPE_BCD: |
|---|
| 310 | data.pin1.encoding = SC_PIN_ENCODING_BCD; |
|---|
| 311 | data.pin2.encoding = SC_PIN_ENCODING_BCD; |
|---|
| 312 | break; |
|---|
| 313 | case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: |
|---|
| 314 | data.pin1.encoding = SC_PIN_ENCODING_ASCII; |
|---|
| 315 | data.pin2.encoding = SC_PIN_ENCODING_ASCII; |
|---|
| 316 | break; |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { |
|---|
| 320 | data.flags |= SC_PIN_CMD_USE_PINPAD; |
|---|
| 321 | if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { |
|---|
| 322 | data.pin1.prompt = "Please enter SO PIN"; |
|---|
| 323 | data.pin2.prompt = "Please enter new SO PIN"; |
|---|
| 324 | } else { |
|---|
| 325 | data.pin1.prompt = "Please enter PIN"; |
|---|
| 326 | data.pin2.prompt = "Please enter new PIN"; |
|---|
| 327 | } |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | r = sc_pin_cmd(card, &data, &pin->tries_left); |
|---|
| 331 | |
|---|
| 332 | out: |
|---|
| 333 | sc_unlock(card); |
|---|
| 334 | return r; |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | |
|---|
| 338 | |
|---|
| 339 | |
|---|
| 340 | int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, |
|---|
| 341 | struct sc_pkcs15_pin_info *pin, |
|---|
| 342 | const u8 *puk, size_t puklen, |
|---|
| 343 | const u8 *newpin, size_t newpinlen) |
|---|
| 344 | { |
|---|
| 345 | int r; |
|---|
| 346 | sc_card_t *card; |
|---|
| 347 | struct sc_pin_cmd_data data; |
|---|
| 348 | struct sc_pkcs15_object *pin_obj, *puk_obj; |
|---|
| 349 | struct sc_pkcs15_pin_info *puk_info = NULL; |
|---|
| 350 | |
|---|
| 351 | |
|---|
| 352 | if ((r = _validate_pin(p15card, pin, newpinlen)) != SC_SUCCESS) |
|---|
| 353 | return r; |
|---|
| 354 | |
|---|
| 355 | card = p15card->card; |
|---|
| 356 | |
|---|
| 357 | |
|---|
| 358 | |
|---|
| 359 | |
|---|
| 360 | |
|---|
| 361 | r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin->auth_id, &pin_obj); |
|---|
| 362 | if (r >= 0 && pin_obj) { |
|---|
| 363 | |
|---|
| 364 | r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj); |
|---|
| 365 | if (r >= 0 && puk_obj) { |
|---|
| 366 | |
|---|
| 367 | puk_info = (struct sc_pkcs15_pin_info *)puk_obj->data; |
|---|
| 368 | } |
|---|
| 369 | } |
|---|
| 370 | if (!puk_info) { |
|---|
| 371 | sc_debug(card->ctx, "Unable to get puk object, using pin object instead!\n"); |
|---|
| 372 | puk_info = pin; |
|---|
| 373 | } |
|---|
| 374 | |
|---|
| 375 | |
|---|
| 376 | if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS) |
|---|
| 377 | return r; |
|---|
| 378 | |
|---|
| 379 | r = sc_lock(card); |
|---|
| 380 | SC_TEST_RET(card->ctx, r, "sc_lock() failed"); |
|---|
| 381 | |
|---|
| 382 | if (pin->path.len > 0) { |
|---|
| 383 | r = sc_select_file(card, &pin->path, NULL); |
|---|
| 384 | if (r) |
|---|
| 385 | goto out; |
|---|
| 386 | } |
|---|
| 387 | |
|---|
| 388 | |
|---|
| 389 | memset(&data, 0, sizeof(data)); |
|---|
| 390 | data.cmd = SC_PIN_CMD_UNBLOCK; |
|---|
| 391 | data.pin_type = SC_AC_CHV; |
|---|
| 392 | data.pin_reference = pin->reference; |
|---|
| 393 | data.pin1.data = puk; |
|---|
| 394 | data.pin1.len = puklen; |
|---|
| 395 | data.pin1.pad_char = pin->pad_char; |
|---|
| 396 | data.pin1.min_length = pin->min_length; |
|---|
| 397 | data.pin1.max_length = pin->max_length; |
|---|
| 398 | data.pin1.pad_length = pin->stored_length; |
|---|
| 399 | data.pin2.data = newpin; |
|---|
| 400 | data.pin2.len = newpinlen; |
|---|
| 401 | data.pin2.pad_char = puk_info->pad_char; |
|---|
| 402 | data.pin2.min_length = puk_info->min_length; |
|---|
| 403 | data.pin2.max_length = puk_info->max_length; |
|---|
| 404 | data.pin2.pad_length = puk_info->stored_length; |
|---|
| 405 | |
|---|
| 406 | if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) |
|---|
| 407 | data.flags |= SC_PIN_CMD_NEED_PADDING; |
|---|
| 408 | |
|---|
| 409 | switch (pin->type) { |
|---|
| 410 | case SC_PKCS15_PIN_TYPE_BCD: |
|---|
| 411 | data.pin1.encoding = SC_PIN_ENCODING_BCD; |
|---|
| 412 | break; |
|---|
| 413 | case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: |
|---|
| 414 | data.pin1.encoding = SC_PIN_ENCODING_ASCII; |
|---|
| 415 | break; |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | switch (puk_info->type) { |
|---|
| 419 | case SC_PKCS15_PIN_TYPE_BCD: |
|---|
| 420 | data.pin2.encoding = SC_PIN_ENCODING_BCD; |
|---|
| 421 | break; |
|---|
| 422 | case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: |
|---|
| 423 | data.pin2.encoding = SC_PIN_ENCODING_ASCII; |
|---|
| 424 | break; |
|---|
| 425 | } |
|---|
| 426 | |
|---|
| 427 | if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { |
|---|
| 428 | data.flags |= SC_PIN_CMD_USE_PINPAD; |
|---|
| 429 | if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { |
|---|
| 430 | data.pin1.prompt = "Please enter PUK"; |
|---|
| 431 | data.pin2.prompt = "Please enter new SO PIN"; |
|---|
| 432 | } else { |
|---|
| 433 | data.pin1.prompt = "Please enter PUK"; |
|---|
| 434 | data.pin2.prompt = "Please enter new PIN"; |
|---|
| 435 | } |
|---|
| 436 | } |
|---|
| 437 | |
|---|
| 438 | r = sc_pin_cmd(card, &data, &pin->tries_left); |
|---|
| 439 | |
|---|
| 440 | out: |
|---|
| 441 | sc_unlock(card); |
|---|
| 442 | return r; |
|---|
| 443 | } |
|---|
| 444 | |
|---|
| 445 | void sc_pkcs15_free_pin_info(sc_pkcs15_pin_info_t *pin) |
|---|
| 446 | { |
|---|
| 447 | free(pin); |
|---|
| 448 | } |
|---|