Changeset 6e70c09 in OpenSC
- Timestamp:
- 06/15/11 08:07:52 (11 months ago)
- Branches:
- master, staging
- Children:
- 2757253, 6c24bd5
- Parents:
- 0ae9962 (diff), d4e90c1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - git-author:
- Martin Paljak <martin@…> (06/15/11 08:07:52)
- git-committer:
- Martin Paljak <martin@…> (06/15/11 08:07:52)
- Files:
-
- 1 added
- 1 deleted
- 10 edited
-
.gitignore (added)
-
Makefile.am (modified) (1 diff)
-
configure.ac (modified) (3 diffs)
-
doc/Makefile.am (modified) (1 diff)
-
doc/svn2cl.xsl (deleted)
-
src/libopensc/card-openpgp.c (modified) (13 diffs)
-
src/libopensc/internal-winscard.h (modified) (1 diff)
-
src/libopensc/reader-pcsc.c (modified) (7 diffs)
-
src/pkcs11/opensc-pkcs11.exports (modified) (1 diff)
-
src/pkcs15init/pkcs15-lib.c (modified) (1 diff)
-
src/tools/opensc-explorer.c (modified) (63 diffs)
-
src/tools/opensc-tool.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Makefile.am
ra7934b3 rd4e90c1 24 24 Generate-ChangeLog: 25 25 rm -f ChangeLog.tmp "$(srcdir)/ChangeLog" 26 test -n "$(SVN)" -a -n "$(XSLTPROC)" 27 if test -d "$(top_srcdir)/.svn"; then \ 28 $(SVN) --verbose --xml log "$(top_srcdir)" | \ 29 $(XSLTPROC) --nonet --stringparam linelen 75 \ 30 --stringparam groupbyday no \ 31 --stringparam include-rev no \ 32 "$(top_srcdir)/doc/svn2cl.xsl" - > ChangeLog.tmp; \ 26 test -n "$(GIT)" 27 if test -d "$(top_srcdir)/.git"; then \ 28 echo "# Generated by Makefile. Do not edit!" > ChangeLog.tmp; \ 29 $(GIT) log >> ChangeLog.tmp; \ 33 30 else \ 34 echo "Warning: Unable to generate ChangeLog from none svn checkout" >&2; \31 echo "Warning: Unable to generate ChangeLog. Need a Git repostiroy." >&2; \ 35 32 echo > ChangeLog.tmp; \ 36 33 fi -
configure.ac
r0dcab4a rd4e90c1 6 6 define([PACKAGE_VERSION_MINOR], [12]) 7 7 define([PACKAGE_VERSION_FIX], [2]) 8 define([PACKAGE_SUFFIX], [- svn])8 define([PACKAGE_SUFFIX], [-pre1]) 9 9 10 10 AC_INIT([opensc],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX]) … … 193 193 ) 194 194 195 dnl These required for svn checkout 196 AC_ARG_VAR([SVN], [subversion utility]) 195 dnl These required for repository checkout 197 196 AC_ARG_VAR([XSLTPROC], [xsltproc utility]) 198 AC_ CHECK_PROGS([SVN],[svn])197 AC_ARG_VAR([git], [git]) 199 198 AC_CHECK_PROGS([XSLTPROC],[xsltproc]) 199 AC_CHECK_PROGS([GIT],[git]) 200 200 201 201 AC_MSG_CHECKING([xsl-stylesheets]) … … 491 491 if test "${enable_man}" = "yes" -o "${enable_doc}" = "yes"; then 492 492 AC_MSG_CHECKING([XSLTPROC requirement]) 493 test -n "${XSLTPROC}" || AC_MSG_ERROR([Missing XSLTPROC svn build with man or doc])493 test -n "${XSLTPROC}" || AC_MSG_ERROR([Missing XSLTPROC]) 494 494 test "${xslstylesheetsdir}" != "no" || AC_MSG_ERROR([Missing xslstylesheetsdir]) 495 495 AC_MSG_RESULT([ok]) -
doc/Makefile.am
r08c111a rd4e90c1 1 1 MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 2 2 3 dist_noinst_SCRIPTS = svn2cl.xslhtml.xsl man.xsl3 dist_noinst_SCRIPTS = html.xsl man.xsl 4 4 dist_noinst_DATA = $(srcdir)/tools/*.xml api.css 5 5 if ENABLE_DOC -
src/libopensc/card-openpgp.c
rbbcb867 r4939432 123 123 static int pgp_get_blob(sc_card_t *card, struct blob *blob, 124 124 unsigned int id, struct blob **ret); 125 static struct blob * pgp_new_blob(struct blob *, unsigned int, int, 126 struct do_info *); 125 static struct blob * pgp_new_blob(sc_card_t *, struct blob *, unsigned int, sc_file_t *); 127 126 static void pgp_free_blob(struct blob *); 128 127 static int pgp_get_pubkey(sc_card_t *, unsigned int, … … 162 161 { 0x00e1, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data }, 163 162 { 0x00e2, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data }, 164 { 0x00ff, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },165 163 { 0x0101, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data }, 166 164 { 0x0102, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data }, 167 165 { 0x0103, SIMPLE, READ_PIN1 | WRITE_PIN1, sc_get_data, sc_put_data }, 168 166 { 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data }, 167 { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL }, 169 168 { 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, 170 169 { 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, … … 217 216 { 0x0103, SIMPLE, READ_PIN1 | WRITE_PIN1, sc_get_data, sc_put_data }, 218 217 { 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data }, 218 { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL }, 219 219 { 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, 220 220 { 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, … … 277 277 card->drv_data = priv; 278 278 279 priv->mf = calloc(1, sizeof(struct blob));280 if (!priv->mf) {281 pgp_finish(card);282 return SC_ERROR_OUT_OF_MEMORY;283 }284 285 279 card->cla = 0x00; 286 280 … … 310 304 } 311 305 306 /* change file path to MF for re-use in MF */ 312 307 sc_format_path("3f00", &file->path); 313 file->type = SC_FILE_TYPE_DF; 314 file->id = 0x3f00; 315 316 priv->mf->file = file; 317 priv->mf->id = 0x3F00; 308 309 /* set up the root of our fake file tree */ 310 priv->mf = pgp_new_blob(card, NULL, 0x3f00, file); 311 if (!priv->mf) { 312 pgp_finish(card); 313 return SC_ERROR_OUT_OF_MEMORY; 314 } 318 315 319 316 /* select MF */ … … 324 321 if (((info->access & READ_MASK) == READ_ALWAYS) && 325 322 (info->get_fn != NULL)) { 326 child = pgp_new_blob(priv->mf, info->id, info->type, info); 323 child = pgp_new_blob(card, priv->mf, info->id, sc_file_new()); 324 327 325 /* catch out of memory condition */ 328 if (child == NULL) 329 break; 330 } 331 } 332 333 /* treat out of memory condition */ 334 if (child == NULL) { 335 pgp_finish(card); 336 return SC_ERROR_OUT_OF_MEMORY; 337 } 338 326 if (child == NULL) { 327 pgp_finish(card); 328 return SC_ERROR_OUT_OF_MEMORY; 329 } 330 } 331 } 339 332 340 333 /* get card_features from ATR & DOs */ … … 401 394 402 395 /* get supported algorithms & key lengths from "algorithm attributes" DOs */ 403 for (i = 0x00c1; i < 0x0c3; i++) {396 for (i = 0x00c1; i <= 0x00c3; i++) { 404 397 unsigned long flags; 405 398 … … 476 469 /* internal: append a blob to the list of children of a given parent blob */ 477 470 static struct blob * 478 pgp_new_blob(struct blob *parent, unsigned int file_id, 479 int file_type, struct do_info *info) 480 { 481 sc_file_t *file = sc_file_new(); 482 struct blob *blob, **p; 483 484 if ((blob = calloc(1, sizeof(*blob))) != NULL) { 471 pgp_new_blob(sc_card_t *card, struct blob *parent, unsigned int file_id, 472 sc_file_t *file) 473 { 474 struct blob *blob = NULL; 475 476 if (file == NULL) 477 return NULL; 478 479 if ((blob = calloc(1, sizeof(struct blob))) != NULL) { 480 struct pgp_priv_data *priv = DRVDATA (card); 481 struct do_info *info; 482 483 blob->file = file; 484 485 blob->file->type = SC_FILE_TYPE_WORKING_EF; /* default */ 486 blob->file->ef_structure = SC_FILE_EF_TRANSPARENT; 487 blob->file->id = file_id; 488 489 blob->id = file_id; 485 490 blob->parent = parent; 486 blob->id = file_id; 487 blob->file = file; 488 blob->info = info; 489 490 file->type = file_type; 491 file->path = parent->file->path; 492 file->ef_structure = SC_FILE_EF_TRANSPARENT; 493 sc_append_file_id(&file->path, file_id); 494 495 for (p = &parent->files; *p; p = &(*p)->next) 496 ; 497 *p = blob; 491 492 if (parent != NULL) { 493 struct blob **p; 494 495 /* set file's path = parent's path + file's id */ 496 blob->file->path = parent->file->path; 497 sc_append_file_id(&blob->file->path, file_id); 498 499 /* append blob to list of parent's children */ 500 for (p = &parent->files; *p != NULL; p = &(*p)->next) 501 ; 502 *p = blob; 503 } 504 else { 505 u8 id_str[2]; 506 507 /* no parent: set file's path = file's id */ 508 sc_format_path(ushort2bebytes(id_str, file_id), &blob->file->path); 509 } 510 511 /* find matching DO info: set file type depending on it */ 512 for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) { 513 if (info->id == file_id) { 514 blob->info = info; 515 blob->file->type = blob->info->type; 516 break; 517 } 518 } 498 519 } 499 520 … … 507 528 { 508 529 if (blob) { 530 if (blob->parent) { 531 struct blob **p; 532 533 /* remove blob from list of parent's children */ 534 for (p = &blob->parent->files; *p != NULL && *p != blob; p = &(*p)->next) 535 ; 536 if (*p == blob) 537 *p = blob->next; 538 } 539 509 540 if (blob->file) 510 541 sc_file_free(blob->file); … … 584 615 while ((int) blob->len > (in - blob->data)) { 585 616 unsigned int cla, tag, tmptag; 586 unsigned int type = SC_FILE_TYPE_WORKING_EF;587 617 size_t len; 588 618 const u8 *data = in; … … 597 627 } 598 628 599 /* create fake file system hierarchy by600 * using constructed DOs as DF */601 if (cla & SC_ASN1_TAG_CONSTRUCTED)602 type = SC_FILE_TYPE_DF;603 604 629 /* undo ASN1's split of tag & class */ 605 630 for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) { … … 608 633 tag |= cla; 609 634 610 if ((new = pgp_new_blob(blob, tag, type, NULL)) == NULL) 635 /* create fake file system hierarchy by 636 * using constructed DOs as DF */ 637 if ((new = pgp_new_blob(card, blob, tag, sc_file_new())) == NULL) 611 638 return SC_ERROR_OUT_OF_MEMORY; 612 639 pgp_set_blob(new, data, len); … … 710 737 LOG_FUNC_RETURN(card->ctx, r); 711 738 712 for (k = 0, blob = blob->files; (blob != NULL) && (k + 2 <= buflen); blob = blob->next, k += 2) { 713 ushort2bebytes(buf + k, blob->id); 739 for (k = 0, blob = blob->files; blob != NULL; blob = blob->next) { 740 if (blob->info != NULL && (blob->info->access & READ_MASK) != READ_NEVER) { 741 if (k + 2 > buflen) 742 LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); 743 744 ushort2bebytes(buf + k, blob->id); 745 k += 2; 746 } 714 747 } 715 748 -
src/libopensc/internal-winscard.h
r19da5d8 r3b63bf3 173 173 #define FEATURE_GET_TLV_PROPERTIES 0x12 174 174 #define FEATURE_CCID_ESC_COMMAND 0x13 175 176 /* properties returned by FEATURE_GET_TLV_PROPERTIES */ 177 #define PCSCv2_PART10_PROPERTY_wLcdLayout 1 178 #define PCSCv2_PART10_PROPERTY_bEntryValidationCondition 2 179 #define PCSCv2_PART10_PROPERTY_bTimeOut2 3 180 #define PCSCv2_PART10_PROPERTY_wLcdMaxCharacters 4 181 #define PCSCv2_PART10_PROPERTY_wLcdMaxLines 5 182 #define PCSCv2_PART10_PROPERTY_bMinPINSize 6 183 #define PCSCv2_PART10_PROPERTY_bMaxPINSize 7 184 #define PCSCv2_PART10_PROPERTY_sFirmwareID 8 185 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 175 186 176 187 /* structures used (but not defined) in PCSC Part 10: -
src/libopensc/reader-pcsc.c
r44cf3d0 r75524a5 87 87 DWORD pin_properties_ioctl; 88 88 89 DWORD get_tlv_properties; 90 89 91 int locked; 90 92 }; … … 790 792 } else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) { 791 793 priv->pin_properties_ioctl = ntohl(pcsc_tlv[i].value); 794 } else if (pcsc_tlv[i].tag == FEATURE_GET_TLV_PROPERTIES) { 795 priv->get_tlv_properties = ntohl(pcsc_tlv[i].value); 792 796 } else { 793 797 sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Reader feature %02x is not supported", pcsc_tlv[i].tag); … … 1030 1034 unsigned int num_watch; 1031 1035 int r = SC_ERROR_INTERNAL; 1036 DWORD dwtimeout; 1032 1037 1033 1038 SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); … … 1168 1173 /* Set the timeout if caller wants to time out */ 1169 1174 if (timeout == -1) { 1170 timeout = INFINITE; 1171 } 1172 1173 rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, timeout, rgReaderStates, num_watch); 1175 dwtimeout = INFINITE; 1176 } 1177 else 1178 dwtimeout = timeout; 1179 1180 rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch); 1174 1181 1175 1182 if (rv == (LONG) SCARD_E_CANCELLED) { … … 1428 1435 } 1429 1436 1437 /* Find a given PCSC v2 part 10 property */ 1438 static int 1439 part10_find_property_by_tag(unsigned char buffer[], int length, 1440 int tag_searched) 1441 { 1442 unsigned char *p; 1443 int found = 0, len, value = -1; 1444 1445 p = buffer; 1446 while (p-buffer < length) 1447 { 1448 if (*p++ == tag_searched) 1449 { 1450 found = 1; 1451 break; 1452 } 1453 1454 /* go to next tag */ 1455 len = *p++; 1456 p += len; 1457 } 1458 1459 if (found) 1460 { 1461 len = *p++; 1462 1463 switch(len) 1464 { 1465 case 1: 1466 value = *p; 1467 break; 1468 case 2: 1469 value = *p + (*(p+1)<<8); 1470 break; 1471 case 4: 1472 value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24); 1473 break; 1474 default: 1475 value = -1; 1476 } 1477 } 1478 1479 return value; 1480 } /* part10_find_property_by_tag */ 1481 1482 /* Make sure the pin min and max are supported by the reader 1483 * and fix the values if needed */ 1484 static int 1485 part10_check_pin_min_max(sc_reader_t *reader, struct sc_pin_cmd_data *data) 1486 { 1487 int r; 1488 unsigned char buffer[256]; 1489 size_t length = sizeof buffer; 1490 struct pcsc_private_data *priv = GET_PRIV_DATA(reader); 1491 1492 r = pcsc_internal_transmit(reader, NULL, 0, buffer, &length, 1493 priv->get_tlv_properties); 1494 SC_TEST_RET(reader->ctx, SC_LOG_DEBUG_NORMAL, r, 1495 "PC/SC v2 part 10: Get TLV properties failed!"); 1496 1497 /* minimum pin size */ 1498 r = part10_find_property_by_tag(buffer, length, 1499 PCSCv2_PART10_PROPERTY_bMinPINSize); 1500 if (r >= 0) 1501 { 1502 unsigned int value = r; 1503 1504 if (data->pin1.min_length < value) 1505 data->pin1.min_length = r; 1506 } 1507 1508 /* maximum pin size */ 1509 r = part10_find_property_by_tag(buffer, length, 1510 PCSCv2_PART10_PROPERTY_bMaxPINSize); 1511 if (r >= 0) 1512 { 1513 unsigned int value = r; 1514 1515 if (data->pin1.max_length > value) 1516 data->pin1.max_length = r; 1517 } 1518 1519 return 0; 1520 } 1521 1430 1522 /* Do the PIN command */ 1431 1523 static int … … 1458 1550 return SC_ERROR_NOT_SUPPORTED; 1459 1551 } 1552 part10_check_pin_min_max(reader, data); 1460 1553 r = part10_build_verify_pin_block(reader, sbuf, &scount, data); 1461 1554 ioctl = priv->verify_ioctl ? priv->verify_ioctl : priv->verify_ioctl_start; … … 1467 1560 return SC_ERROR_NOT_SUPPORTED; 1468 1561 } 1562 part10_check_pin_min_max(reader, data); 1469 1563 r = part10_build_modify_pin_block(reader, sbuf, &scount, data); 1470 1564 ioctl = priv->modify_ioctl ? priv->modify_ioctl : priv->modify_ioctl_start; -
src/pkcs11/opensc-pkcs11.exports
r0a809dd r5a23069 1 C_CancelFunction2 C_CloseAllSessions3 C_CloseSession4 C_CopyObject5 C_CreateObject6 C_Decrypt7 C_DecryptDigestUpdate8 C_DecryptFinal9 C_DecryptInit10 C_DecryptUpdate11 C_DecryptVerifyUpdate12 C_DeriveKey13 C_DestroyObject14 C_Digest15 C_DigestEncryptUpdate16 C_DigestFinal17 C_DigestInit18 C_DigestKey19 C_DigestUpdate20 C_Encrypt21 C_EncryptFinal22 C_EncryptInit23 C_EncryptUpdate24 C_Finalize25 C_FindObjects26 C_FindObjectsFinal27 C_FindObjectsInit28 C_GenerateKey29 C_GenerateKeyPair30 C_GenerateRandom31 C_GetAttributeValue32 1 C_GetFunctionList 33 C_GetFunctionStatus34 C_GetInfo35 C_GetMechanismInfo36 C_GetMechanismList37 C_GetObjectSize38 C_GetOperationState39 C_GetSessionInfo40 C_GetSlotInfo41 C_GetSlotList42 C_GetTokenInfo43 C_InitPIN44 C_InitToken45 C_Initialize46 C_Login47 C_Logout48 C_OpenSession49 C_SeedRandom50 C_SetAttributeValue51 C_SetOperationState52 C_SetPIN53 C_Sign54 C_SignEncryptUpdate55 C_SignFinal56 C_SignInit57 C_SignRecover58 C_SignRecoverInit59 C_SignUpdate60 C_UnwrapKey61 C_Verify62 C_VerifyFinal63 C_VerifyInit64 C_VerifyRecover65 C_VerifyRecoverInit66 C_VerifyUpdate67 C_WaitForSlotEvent68 C_WrapKey -
src/pkcs15init/pkcs15-lib.c
rd888b3f r9027279 1066 1066 } 1067 1067 1068 int1068 static int 1069 1069 sc_pkcs15init_encode_prvkey_content(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *prvkey, 1070 1070 struct sc_pkcs15_object *object) -
src/tools/opensc-explorer.c
r661cc0d r2faad42 38 38 #define DIM(v) (sizeof(v)/sizeof((v)[0])) 39 39 40 /* type for associations of IDs to names */ 41 typedef struct _id2str { 42 unsigned int id; 43 const char *str; 44 } id2str_t; 45 40 46 static const char *app_name = "opensc-explorer"; 41 47 … … 66 72 }; 67 73 68 static size_t hex2binary(u8 *out, size_t outlen, const char *in); 74 75 /* declare functions called by user commands */ 76 static int do_ls(int argc, char **argv); 77 static int do_cd(int argc, char **argv); 78 static int do_cat(int argc, char **argv); 79 static int do_info(int argc, char **argv); 80 static int do_create(int argc, char **argv); 81 static int do_mkdir(int argc, char **argv); 82 static int do_delete(int argc, char **argv); 83 static int do_verify(int argc, char **argv); 84 static int do_change(int argc, char **argv); 85 static int do_unblock(int argc, char **argv); 86 static int do_get(int argc, char **argv); 87 static int do_update_binary(int argc, char **argv); 88 static int do_update_record(int argc, char **argv); 89 static int do_put(int argc, char **argv); 90 static int do_debug(int argc, char **argv); 91 static int do_erase(int argc, char **argv); 92 static int do_random(int argc, char **argv); 93 static int do_get_data(int argc, char **argv); 94 static int do_put_data(int argc, char **argv); 95 static int do_apdu(int argc, char **argv); 96 static int do_asn1(int argc, char **argv); 97 static int do_help(int argc, char **argv); 98 static int do_quit(int argc, char **argv); 99 69 100 70 101 struct command { 102 int (*func)(int, char **); 71 103 const char * name; 72 int (*func)(int, char **);104 const char * args; 73 105 const char * help; 74 106 }; 107 108 static struct command cmds[] = { 109 { do_ls, 110 "ls", "", 111 "list all files in the current DF" }, 112 { do_cd, 113 "cd", "{.. | <file id> | aid:<DF name>}", 114 "change to another DF" }, 115 { do_cat, 116 "cat", "[<file id> | sfi:<sfi id>]" 117 , "print the contents of an EF" }, 118 { do_info, 119 "info", "[<file id>]", 120 "display attributes of card file" }, 121 { do_create, 122 "create", "<file id> <size>", 123 "create a new EF" }, 124 { do_mkdir, 125 "mkdir", "<file id> <size>", 126 "create a new DF" }, 127 { do_delete, 128 "delete", "<file id>", 129 "remove an EF/DF" }, 130 { do_delete, 131 "rm", "<file id>", 132 "remove an EF/DF" }, 133 { do_verify, 134 "verify", "<key type><key ref> [<pin>]", 135 "present a PIN or key to the card" }, 136 { do_change, 137 "change", "CHV<pin ref> [[<old pin>] <new pin>]", 138 "change a PIN" }, 139 { do_unblock, 140 "unblock", "CHV<pin ref> [<puk> [<new pin>]]", 141 "unblock a PIN" }, 142 { do_put, 143 "put", "<file id> [<input file>]", 144 "copy a local file to the card" }, 145 { do_get, 146 "get", "<file id> [<output file>]", 147 "copy an EF to a local file" }, 148 { do_get_data, 149 "do_get", "<hex tag> [<output file>]", 150 "get a data object" }, 151 { do_put_data, 152 "do_put", "<hex tag> <data>", 153 "put a data object" }, 154 { do_erase, 155 "erase", "", 156 "erase card" }, 157 { do_random, 158 "random", "<count>", 159 "obtain <count> random bytes from card" }, 160 { do_update_record, 161 "update_record", "<file id> <rec no> <rec offs> <data>", 162 "update record" }, 163 { do_update_binary, 164 "update_binary", "<file id> <offs> <data>", 165 "update binary" }, 166 { do_apdu, 167 "apdu", "<data>+", 168 "send a custom apdu command" }, 169 { do_asn1, 170 "asn1", "[<file id>]", 171 "decode an asn1 file" }, 172 { do_debug, 173 "debug", "[<value>]", 174 "get/set the debug level" }, 175 { do_quit, 176 "quit", "", 177 "quit this program" }, 178 { do_quit, 179 "exit", "", 180 "quit this program" }, 181 { do_help, 182 "help", "", 183 "show this help" }, 184 { NULL, NULL, NULL, NULL } 185 }; 186 187 188 static char *path_to_filename(const sc_path_t *path, const char sep) 189 { 190 static char buf[2*SC_MAX_PATH_STRING_SIZE]; 191 int i, j; 192 193 for (i = 0, j = 0; path != NULL && i < path->len; i++) { 194 if (sep != '\0' && i > 0 && (i & 1) == 0) 195 j += sprintf(buf+j, "%c", sep); 196 j += sprintf(buf+j, "%02X", path->value[i]); 197 } 198 buf[j] = 0; 199 200 return buf; 201 } 202 203 static int parse_string_or_hexdata(const char *in, u8 *out, size_t *outlen) 204 { 205 if (in == NULL) 206 return SC_ERROR_INVALID_ARGUMENTS; 207 208 if (*in == '"') { 209 u8 quote = *in++; 210 size_t count = 0; 211 212 while (*in != quote && *in != '\0' && count < *outlen) 213 out[count++] = *in++; 214 if (*in == '\0') 215 return SC_ERROR_INVALID_ARGUMENTS; 216 if (count >= *outlen) 217 return SC_ERROR_BUFFER_TOO_SMALL; 218 219 *outlen = count; 220 return 0; 221 } 222 else 223 return sc_hex_to_bin(in, out, outlen); 224 } 225 226 static int usage(int (*func)(int, char **)) 227 { 228 struct command *cmd; 229 230 for (cmd = cmds; cmd->func; cmd++) 231 if (cmd->func == func) 232 printf("Usage: %s %s\n", cmd->name, cmd->args); 233 return -1; 234 } 75 235 76 236 static void die(int ret) … … 131 291 /* DF aid */ 132 292 const char *p = arg + strlen("aid:"); 133 path->len = hex2binary(path->value, sizeof(path->value), p); 293 int r; 294 134 295 path->type = SC_PATH_TYPE_DF_NAME; 296 path->len = sizeof(path->value); 297 if ((r = sc_hex_to_bin(p, path->value, &path->len)) < 0) { 298 printf("Error parsing AID: %s\n", p); 299 return r; 300 } 135 301 } else { 136 302 /* file id */ 137 303 unsigned int buf[2]; 138 304 u8 cbuf[2]; 139 305 140 306 if (strlen(arg) != 4) { 141 307 printf("Wrong ID length.\n"); … … 151 317 path->len = 2; 152 318 memcpy(path->value, cbuf, 2); 153 if (is_id) 154 path->type = SC_PATH_TYPE_FILE_ID; 155 else 156 path->type = SC_PATH_TYPE_PATH; 319 path->type = (is_id) ? SC_PATH_TYPE_FILE_ID : SC_PATH_TYPE_PATH; 157 320 } else { 158 321 *path = current_path; … … 173 336 } 174 337 175 return 0; 338 return 0; 176 339 } 177 340 … … 210 373 211 374 if (argc) 212 goto usage; 375 return usage(do_ls); 376 213 377 r = sc_list_files(card, buf, sizeof(buf)); 214 378 if (r < 0) { … … 231 395 } 232 396 } 233 397 234 398 r = sc_select_file(card, &path, &file); 235 399 if (r) { … … 245 409 } 246 410 return 0; 247 usage:248 puts("Usage: ls");249 return -1;250 411 } 251 412 … … 257 418 258 419 if (argc != 1) 259 goto usage; 420 return usage(do_cd); 421 260 422 if (strcmp(argv[0], "..") == 0) { 261 423 path = current_path; … … 284 446 } 285 447 if (arg_to_path(argv[0], &path, 0) != 0) 286 goto usage;448 return usage(do_cd); 287 449 288 450 r = sc_select_file(card, &path, &file); … … 303 465 304 466 return 0; 305 usage:306 puts("Usage: cd <file_id>|aid:<DF name>");307 return -1;308 467 } 309 468 … … 314 473 size_t count; 315 474 int r; 316 475 317 476 count = file->size; 318 477 while (count) { … … 365 524 366 525 if (argc > 1) 367 goto usage; 526 return usage(do_cat); 527 368 528 if (!argc) { 369 529 path = current_path; … … 386 546 if ((sfi < 1) || (sfi > 30)) { 387 547 printf("Invalid SFI: %s\n", sfi_n); 388 goto usage;548 return usage(do_cat); 389 549 } 390 550 } else { 391 551 if (arg_to_path(argv[0], &path, 0) != 0) 392 goto usage; 552 return usage(do_cat); 553 393 554 r = sc_select_file(card, &path, &file); 394 555 if (r) { … … 408 569 else 409 570 read_and_print_record_file(file, sfi); 410 571 411 572 err = 0; 412 413 573 err: 414 574 if (not_current) { 415 if (file != NULL) {575 if (file != NULL) 416 576 sc_file_free(file); 417 }418 577 select_current_path_or_die(); 419 578 } 420 579 421 580 return -err; 422 usage:423 puts("Usage: cat [file_id] or");424 puts(" cat sfi:<sfi_id>");425 return -1;426 581 } 427 582 … … 433 588 const char *st; 434 589 int r, not_current = 1; 590 const id2str_t *ac_ops = NULL; 435 591 436 592 if (!argc) { … … 440 596 } else if (argc == 1) { 441 597 if (arg_to_path(argv[0], &path, 0) != 0) 442 goto usage; 598 return usage(do_info); 599 443 600 r = sc_select_file(card, &path, &file); 444 601 if (r) { … … 447 604 } 448 605 } else 449 goto usage;606 return usage(do_info); 450 607 451 608 switch (file->type) { … … 462 619 } 463 620 printf("\n%s ID %04X\n\n", st, file->id); 464 printf("%-15s", "File path:"); 465 for (i = 0; i < path.len; i++) { 466 for (i = 0; i < path.len; i++) { 467 if ((i & 1) == 0 && i) 468 printf("/"); 469 printf("%02X", path.value[i]); 470 } 471 } 472 printf("\n%-15s%lu bytes\n", "File size:", (unsigned long) file->size); 621 printf("%-15s%s\n", "File path:", path_to_filename(&path, '/')); 622 printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size); 473 623 474 624 if (file->type == SC_FILE_TYPE_DF) { 475 const char *ops[] = { 476 "SELECT", "LOCK", "DELETE", "CREATE", "REHABILITATE", 477 "INVALIDATE", "LIST FILES", "CRYPTO", "DELETE SELF" 625 static const id2str_t ac_ops_df[] = { 626 { SC_AC_OP_SELECT, "SELECT" }, 627 { SC_AC_OP_LOCK, "LOCK" }, 628 { SC_AC_OP_DELETE, "DELETE" }, 629 { SC_AC_OP_CREATE, "CREATE" }, 630 { SC_AC_OP_REHABILITATE, "REHABILITATE" }, 631 { SC_AC_OP_INVALIDATE, "INVALIDATE" }, 632 { SC_AC_OP_LIST_FILES, "LIST FILES" }, 633 { SC_AC_OP_CRYPTO, "CRYPTO" }, 634 { SC_AC_OP_DELETE_SELF, "DELETE SELF" }, 635 { 0, NULL } 478 636 }; 637 479 638 if (file->namelen) { 480 639 printf("%-15s", "DF name:"); … … 482 641 printf("\n"); 483 642 } 484 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { 485 char buf[80]; 486 487 sprintf(buf, "ACL for %s:", ops[i]); 488 printf("%-25s%s\n", buf, util_acl_to_str(sc_file_get_acl_entry(file, i))); 489 } 643 644 ac_ops = ac_ops_df; 490 645 } else { 491 const char *structs[] = { 492 "Unknown", "Transparent", "Linear fixed", 493 "Linear fixed, SIMPLE-TLV", "Linear variable", 494 "Linear variable TLV", "Cyclic, SIMPLE-TLV", 646 static const id2str_t ac_ops_ef[] = { 647 { SC_AC_OP_READ, "READ" }, 648 { SC_AC_OP_UPDATE, "UPDATE" }, 649 { SC_AC_OP_DELETE, "DELETE" }, 650 { SC_AC_OP_WRITE, "WRITE" }, 651 { SC_AC_OP_REHABILITATE, "REHABILITATE" }, 652 { SC_AC_OP_INVALIDATE, "INVALIDATE" }, 653 { SC_AC_OP_LIST_FILES, "LIST FILES" }, 654 { SC_AC_OP_CRYPTO, "CRYPTO" }, 655 { 0, NULL } 495 656 }; 496 const struct { 497 const char * label; 498 int op; 499 } ops[] = { 500 { "READ", SC_AC_OP_READ }, 501 { "UPDATE", SC_AC_OP_UPDATE }, 502 { "DELETE", SC_AC_OP_DELETE }, 503 { "WRITE", SC_AC_OP_WRITE }, 504 { "REHABILITATE", SC_AC_OP_REHABILITATE }, 505 { "INVALIDATE", SC_AC_OP_INVALIDATE }, 506 { "LIST_FILES", SC_AC_OP_LIST_FILES }, 507 { "CRYPTO", SC_AC_OP_CRYPTO }, 657 const id2str_t ef_type_name[] = { 658 { SC_FILE_EF_TRANSPARENT, "Transparent" }, 659 { SC_FILE_EF_LINEAR_FIXED, "Linear fixed" }, 660 { SC_FILE_EF_LINEAR_FIXED_TLV, "Linear fixed, SIMPLE-TLV" }, 661 { SC_FILE_EF_LINEAR_VARIABLE, "Linear variable" }, 662 { SC_FILE_EF_LINEAR_VARIABLE_TLV, "Linear variable, SIMPLE-TLV" }, 663 { SC_FILE_EF_CYCLIC, "Cyclic" }, 664 { SC_FILE_EF_CYCLIC_TLV, "Cyclic, SIMPLE-TLV" }, 665 { 0, NULL } 508 666 }; 509 printf("%-15s%s\n", "EF structure:", structs[file->ef_structure]); 510 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { 511 char buf[80]; 512 513 sprintf(buf, "ACL for %s:", ops[i].label); 514 printf("%-25s%s\n", buf, util_acl_to_str(sc_file_get_acl_entry(file, ops[i].op))); 515 } 516 } 667 const char *ef_type = "Unknown"; 668 669 for (i = 0; ef_type_name[i].str != NULL; i++) 670 if (file->ef_structure == ef_type_name[i].id) 671 ef_type = ef_type_name[i].str; 672 printf("%-15s%s\n", "EF structure:", ef_type); 673 674 ac_ops = ac_ops_ef; 675 } 676 677 for (i = 0; ac_ops != NULL && ac_ops[i].str != NULL; i++) { 678 int len = strlen(ac_ops[i].str); 679 680 printf("ACL for %s:%*s %s\n", 681 ac_ops[i].str, 682 (12 > len) ? (12 - len) : 0, "", 683 util_acl_to_str(sc_file_get_acl_entry(file, ac_ops[i].id))); 684 } 685 517 686 if (file->prop_attr_len) { 518 687 printf("%-25s", "Proprietary attributes:"); 519 for (i = 0; i < file->prop_attr_len; i++) 520 printf("%02X ", file->prop_attr[i]); 688 util_hex_dump(stdout, file->prop_attr, file->prop_attr_len, " "); 521 689 printf("\n"); 522 690 } 523 691 if (file->sec_attr_len) { 524 692 printf("%-25s", "Security attributes:"); 525 for (i = 0; i < file->sec_attr_len; i++) 526 printf("%02X ", file->sec_attr[i]); 693 util_hex_dump(stdout, file->sec_attr, file->sec_attr_len, " "); 527 694 printf("\n"); 528 695 } … … 533 700 } 534 701 return 0; 535 536 usage:537 puts("Usage: info [file_id]");538 return -1;539 702 } 540 703 … … 542 705 { 543 706 int r; 544 707 545 708 r = sc_create_file(card, file); 546 709 if (r) { … … 562 725 563 726 if (argc != 2) 564 goto usage;727 return usage(do_create); 565 728 if (arg_to_path(argv[0], &path, 1) != 0) 566 goto usage;729 return usage(do_create); 567 730 /* %z isn't supported everywhere */ 568 731 if (sscanf(argv[1], "%u", &size) != 1) 569 goto usage;732 return usage(do_create); 570 733 file = sc_file_new(); 571 734 file->id = (path.value[0] << 8) | path.value[1]; … … 576 739 for (op = 0; op < SC_MAX_AC_OPS; op++) 577 740 sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); 578 741 579 742 r = create_file(file); 580 743 sc_file_free(file); 581 744 return r; 582 usage:583 printf("Usage: create <file_id> <file_size>\n");584 return -1;585 745 } 586 746 … … 593 753 594 754 if (argc != 2) 595 goto usage;755 return usage(do_mkdir); 596 756 if (arg_to_path(argv[0], &path, 1) != 0) 597 goto usage;757 return usage(do_mkdir); 598 758 if (sscanf(argv[1], "%u", &size) != 1) 599 goto usage;759 return usage(do_mkdir); 600 760 file = sc_file_new(); 601 761 file->id = (path.value[0] << 8) | path.value[1]; … … 609 769 sc_file_free(file); 610 770 return r; 611 usage:612 printf("Usage: mkdir <file_id> <df_size>\n");613 return -1;614 771 } 615 772 … … 620 777 621 778 if (argc != 1) 622 goto usage;779 return usage(do_delete); 623 780 if (arg_to_path(argv[0], &path, 1) != 0) 624 goto usage;781 return usage(do_delete); 625 782 if (path.len != 2) 626 goto usage;783 return usage(do_delete); 627 784 path.type = SC_PATH_TYPE_FILE_ID; 628 785 r = sc_delete_file(card, &path); … … 632 789 } 633 790 return 0; 634 usage:635 printf("Usage: delete <file_id>\n");636 return -1;637 791 } 638 792 639 793 static int do_verify(int argc, char **argv) 640 794 { 641 struct { 642 const char * name; 643 int type; 644 } typeNames[] = { 645 { "CHV", SC_AC_CHV }, 646 { "KEY", SC_AC_AUT }, 647 { "AUT", SC_AC_AUT }, 648 { "PRO", SC_AC_PRO }, 649 { NULL, SC_AC_NONE } 795 const id2str_t typeNames[] = { 796 { SC_AC_CHV, "CHV" }, 797 { SC_AC_AUT, "KEY" }, 798 { SC_AC_AUT, "AUT" }, 799 { SC_AC_PRO, "PRO" }, 800 { SC_AC_NONE, NULL, } 650 801 }; 651 802 int r, tries_left = -1; 652 803 u8 buf[64]; 653 const char *s;654 804 size_t buflen = sizeof(buf), i; 655 805 struct sc_pin_cmd_data data; … … 662 812 663 813 data.pin_type = SC_AC_NONE; 664 for (i = 0; typeNames[i]. name; i++) {665 if (strncasecmp(argv[0], typeNames[i]. name, 3) == 0) {666 data.pin_type = typeNames[i]. type;814 for (i = 0; typeNames[i].str; i++) { 815 if (strncasecmp(argv[0], typeNames[i].str, 3) == 0) { 816 data.pin_type = typeNames[i].id; 667 817 break; 668 818 } … … 685 835 data.pin1.prompt = "Please enter PIN"; 686 836 data.flags |= SC_PIN_CMD_USE_PINPAD; 687 } else if (argv[1][0] == '"') {688 for (s=argv[1]+1, i=0; i < sizeof(buf) && *s && *s != '"';i++)689 buf[i] = *s++;690 data.pin1.data = buf;691 data.pin1.len = i;692 837 } else { 693 r = sc_hex_to_bin(argv[1], buf, &buflen);838 r = parse_string_or_hexdata(argv[1], buf, &buflen); 694 839 if (0 != r) { 695 840 printf("Invalid key value.\n"); … … 714 859 return 0; 715 860 usage: 716 printf("Usage: verify <key type><key ref> [< key in hex>]\n");861 printf("Usage: verify <key type><key ref> [<pin>]\n"); 717 862 printf("Possible values of <key type>:\n"); 718 for (i = 0; typeNames[i]. name; i++)719 printf("\t%s\n", typeNames[i]. name);863 for (i = 0; typeNames[i].str; i++) 864 printf("\t%s\n", typeNames[i].str); 720 865 printf("Example: verify CHV2 31:32:33:34:00:00:00:00\n"); 721 866 printf("If key is omitted, card reader's keypad will be used to collect PIN.\n"); … … 729 874 u8 oldpin[30]; 730 875 u8 newpin[30]; 731 const char *s; 732 size_t oldpinlen = sizeof(oldpin), i; 733 size_t newpinlen = sizeof(newpin); 734 876 size_t oldpinlen = 0; 877 size_t newpinlen = 0; 878 735 879 if (argc < 1 || argc > 3) 736 880 goto usage; … … 743 887 goto usage; 744 888 } 745 argc--; 746 argv++; 747 748 if (argc == 0) { 749 /* set without verification */ 750 oldpinlen = 0; 751 newpinlen = 0; 752 } else if (argc == 1) { 753 /* set without verification */ 754 oldpinlen = 0; 755 } else { 756 if (argv[0][0] == '"') { 757 for (s = argv[0] + 1, i = 0; 758 i < sizeof(oldpin) && *s && *s != '"'; i++) 759 oldpin[i] = *s++; 760 oldpinlen = i; 761 } else if (sc_hex_to_bin(argv[0], oldpin, &oldpinlen) != 0) { 889 890 if (argc == 3) { 891 oldpinlen = sizeof(oldpin); 892 if (parse_string_or_hexdata(argv[1], oldpin, &oldpinlen) != 0) { 762 893 printf("Invalid key value.\n"); 763 894 goto usage; 764 895 } 765 argc--; 766 argv++; 767 } 768 769 if (argc) { 770 if (argv[0][0] == '"') { 771 for (s = argv[0] + 1, i = 0; 772 i < sizeof(newpin) && *s && *s != '"'; i++) 773 newpin[i] = *s++; 774 newpinlen = i; 775 } else if (sc_hex_to_bin(argv[0], newpin, &newpinlen) != 0) { 896 } 897 898 if (argc >= 2) { 899 newpinlen = sizeof(newpin); 900 if (parse_string_or_hexdata(argv[argc-1], newpin, &newpinlen) != 0) { 776 901 printf("Invalid key value.\n"); 777 902 goto usage; … … 808 933 { 809 934 int ref, r; 810 u8 puk_buf[30], *puk = NULL; 811 u8 newpin_buf[30], *newpin = NULL; 812 const char *s; 813 size_t puklen = sizeof(puk_buf), i; 814 size_t newpinlen = sizeof(newpin_buf); 815 935 u8 puk[30]; 936 u8 newpin[30]; 937 size_t puklen = 0; 938 size_t newpinlen = 0; 939 816 940 if (argc < 1 || argc > 3) 817 941 goto usage; … … 824 948 goto usage; 825 949 } 826 argc--; 827 argv++; 828 829 if (argc == 0) { 830 puklen = 0; 831 puk = NULL; 832 } else { 833 if (argv[0][0] == '"') { 834 for (s = argv[0] + 1, i = 0; 835 i < sizeof(puk_buf) && *s && *s != '"'; i++) 836 puk_buf[i] = *s++; 837 puklen = i; 838 } else if (sc_hex_to_bin(argv[0], puk_buf, &puklen) != 0) { 950 951 if (argc > 1) { 952 puklen = sizeof(puk); 953 if (parse_string_or_hexdata(argv[1], puk, &puklen) != 0) { 839 954 printf("Invalid key value.\n"); 840 955 goto usage; 841 956 } 842 puk = &puk_buf[0]; 843 844 argc--; 845 argv++; 846 } 847 848 if (argc) { 849 if (argv[0][0] == '"') { 850 for (s = argv[0] + 1, i = 0; 851 i < sizeof(newpin_buf) && *s && *s != '"'; i++) 852 newpin_buf[i] = *s++; 853 newpinlen = i; 854 } else if (sc_hex_to_bin(argv[0], newpin_buf, &newpinlen) != 0) { 957 } 958 959 if (argc > 2) { 960 newpinlen = sizeof(newpin); 961 if (parse_string_or_hexdata(argv[2], newpin, &newpinlen) != 0) { 855 962 printf("Invalid key value.\n"); 856 963 goto usage; 857 964 } 858 859 newpin = &newpin_buf[0];860 }861 else {862 newpinlen = 0;863 newpin = NULL;864 965 } 865 966 866 967 r = sc_reset_retry_counter (card, SC_AC_CHV, ref, 867 puk , puklen,868 newpin , newpinlen);968 puklen ? puk : NULL, puklen, 969 newpinlen ? newpin : NULL, newpinlen); 869 970 if (r) { 870 971 if (r == SC_ERROR_PIN_CODE_INCORRECT) … … 876 977 return 0; 877 978 usage: 878 printf("Usage: unblock CHV<pin ref> [<puk> ] [<new pin>]\n");979 printf("Usage: unblock CHV<pin ref> [<puk> [<new pin>]]\n"); 879 980 printf("PUK and PIN values can be hexadecimal, ASCII, empty (\"\") or absent\n"); 880 981 printf("Examples:\n"); … … 897 998 sc_path_t path; 898 999 sc_file_t *file = NULL; 899 char fbuf[256],*filename;1000 char *filename; 900 1001 FILE *outf = NULL; 901 1002 902 1003 if (argc < 1 || argc > 2) 903 goto usage;1004 return usage(do_get); 904 1005 if (arg_to_path(argv[0], &path, 0) != 0) 905 goto usage; 906 if (argc == 2) 907 filename = argv[1]; 908 else { 909 size_t i = 0; 910 911 while (2*i < path.len) { 912 sprintf(&fbuf[5*i], "%02X%02X_", path.value[2*i], path.value[2*i+1]); 913 i++; 914 } 915 fbuf[5*i-1] = 0; 916 filename = fbuf; 917 } 1006 return usage(do_get); 1007 1008 filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); 918 1009 outf = (strcmp(filename, "-") == 0) 919 1010 ? stdout … … 958 1049 idx, argv[0], filename); 959 1050 } 960 1051 961 1052 err = 0; 962 1053 err: … … 967 1058 select_current_path_or_die(); 968 1059 return -err; 969 usage:970 printf("Usage: get <file id> [output file]\n");971 return -1;972 }973 974 static size_t hex2binary(u8 *out, size_t outlen, const char *in)975 {976 size_t inlen = strlen(in), len = outlen;977 const char *p = in;978 int s = 0;979 980 out--;981 while (inlen && (len || s)) {982 char c = *p++;983 inlen--;984 if (!isxdigit(c))985 continue;986 if (c >= '0' && c <= '9')987 c -= '0';988 else if (c >= 'a' && c <= 'f')989 c -= 'a' - 10;990 else /* (c >= 'A' && c <= 'F') */991 c -= 'A' - 10;992 if (s)993 *out <<= 4;994 else {995 len--;996 *(++out) = 0;997 }998 s = !s;999 *out |= (u8)c;1000 }1001 if (s) {1002 printf("Error: the number of hex digits must be even.\n");1003 return 0;1004 }1005 1006 return outlen - len;1007 1060 } 1008 1061 … … 1010 1063 { 1011 1064 u8 buf[240]; 1012 int r, err = 1, in_len; 1065 size_t buflen = sizeof(buf); 1066 int r, err = 1; 1013 1067 int offs; 1014 1068 sc_path_t path; 1015 1069 sc_file_t *file; 1016 char *in_str; 1017 1018 if (argc < 2 || argc > 3) 1019 goto usage; 1070 1071 if (argc != 3) 1072 return usage(do_update_binary); 1020 1073 if (arg_to_path(argv[0], &path, 0) != 0) 1021 goto usage;1074 return usage(do_update_binary); 1022 1075 offs = strtol(argv[1],NULL,10); 1023 1076 1024 in_str = argv[2]; 1025 printf("in: %i; %s\n", offs, in_str); 1026 if (*in_str=='\"') { 1027 in_len = strlen(in_str)-2 >= sizeof(buf) ? sizeof(buf)-1 : strlen(in_str)-2; 1028 strncpy((char *) buf, in_str+1, in_len); 1029 } else { 1030 in_len = hex2binary(buf, sizeof(buf), in_str); 1031 if (!in_len) { 1032 printf("unable to parse hex value\n"); 1033 return -1; 1034 } 1035 } 1036 1077 printf("in: %i; %s\n", offs, argv[2]); 1078 1079 r = parse_string_or_hexdata(argv[2], buf, &buflen); 1080 if (r < 0) { 1081 printf("unable to parse data\n"); 1082 return -1; 1083 } 1084 1037 1085 r = sc_select_file(card, &path, &file); 1038 1086 if (r) { … … 1045 1093 goto err; 1046 1094 } 1047 1048 r = sc_update_binary(card, offs, buf, in_len, 0);1095 1096 r = sc_update_binary(card, offs, buf, buflen, 0); 1049 1097 if (r < 0) { 1050 1098 printf("Cannot update %04X; return %i\n", file->id, r); … … 1056 1104 1057 1105 err = 0; 1058 1059 1106 err: 1060 1107 sc_file_free(file); 1061 1108 select_current_path_or_die(); 1062 1109 return -err; 1063 usage:1064 printf("Usage: update <file id> offs <hex value> | <'\"' enclosed string>\n");1065 return -1;1066 1110 } 1067 1111 … … 1069 1113 { 1070 1114 u8 buf[240]; 1115 size_t buflen; 1071 1116 int r, i, err = 1; 1072 1117 int rec, offs; 1073 1118 sc_path_t path; 1074 1119 sc_file_t *file; 1075 char *in_str; 1076 1077 if (argc < 3 || argc > 4) 1078 goto usage; 1120 1121 if (argc != 4) 1122 return usage(do_update_record); 1079 1123 if (arg_to_path(argv[0], &path, 0) != 0) 1080 goto usage;1124 return usage(do_update_record); 1081 1125 rec = strtol(argv[1],NULL,10); 1082 1126 offs = strtol(argv[2],NULL,10); 1083 1127 1084 in_str = argv[3]; 1085 printf("in: %i; %i; %s\n", rec, offs, in_str); 1128 printf("in: %i; %i; %s\n", rec, offs, argv[3]); 1086 1129 1087 1130 r = sc_select_file(card, &path, &file); … … 1098 1141 goto err; 1099 1142 } 1100 1143 1101 1144 r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); 1102 1145 if (r<0) { … … 1105 1148 } 1106 1149 1107 i = hex2binary(buf + offs, sizeof(buf) - offs, in_str); 1150 buflen = sizeof(buf) - offs; 1151 i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); 1108 1152 if (!i) { 1109 printf("unable to parse hex value\n");1153 printf("unable to parse data\n"); 1110 1154 goto err; 1111 1155 } … … 1119 1163 printf("Total of %d bytes written to record %i at %i offset.\n", 1120 1164 i, rec, offs); 1165 1121 1166 err = 0; 1122 1123 1167 err: 1124 1168 sc_file_free(file); 1125 1169 select_current_path_or_die(); 1126 1170 return -err; 1127 usage:1128 printf("Usage: update_record <file id> rec_nr rec_offs <hex value>\n");1129 return -1;1130 1171 } 1131 1172 … … 1143 1184 1144 1185 if (argc < 1 || argc > 2) 1145 goto usage;1186 return usage(do_put); 1146 1187 if (arg_to_path(argv[0], &path, 0) != 0) 1147 goto usage; 1148 if (argc == 2) 1149 filename = argv[1]; 1150 else { 1151 sprintf((char *) buf, "%02X%02X", path.value[0], path.value[1]); 1152 filename = (char *) buf; 1153 } 1188 return usage(do_put); 1189 1190 filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); 1154 1191 outf = fopen(filename, "rb"); 1155 1192 if (outf == NULL) { … … 1188 1225 1189 1226 err = 0; 1190 1191 1227 err: 1192 1193 1228 if (file) 1194 1229 sc_file_free(file); … … 1197 1232 select_current_path_or_die(); 1198 1233 return -err; 1199 usage:1200 printf("Usage: put <file id> [input file]\n");1201 return -1;1202 1234 } 1203 1235 … … 1221 1253 1222 1254 1223 static int 1224 do_erase(int argc, char **argv) 1255 static int do_erase(int argc, char **argv) 1225 1256 { 1226 1257 int r; 1227 1258 1228 1259 if (argc != 0) 1229 goto usage;1260 return usage(do_erase); 1230 1261 1231 1262 r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL); … … 1235 1266 } 1236 1267 return 0; 1237 1238 usage: 1239 printf("Usage: erase\n"); 1240 return -1; 1241 } 1242 1243 static int 1244 do_random(int argc, char **argv) 1268 } 1269 1270 static int do_random(int argc, char **argv) 1245 1271 { 1246 1272 unsigned char buffer[128]; … … 1248 1274 1249 1275 if (argc != 1) 1250 goto usage;1276 return usage(do_random); 1251 1277 1252 1278 count = atoi(argv[0]); … … 1264 1290 util_hex_dump_asc(stdout, buffer, count, 0); 1265 1291 return 0; 1266 1267 usage:1268 printf("Usage: random count\n");1269 return -1;1270 1292 } 1271 1293 … … 1278 1300 1279 1301 if (argc != 1 && argc != 2) 1280 goto usage;1302 return usage(do_get_data); 1281 1303 1282 1304 tag = strtoul(argv[0], NULL, 16); … … 1302 1324 1303 1325 return 0; 1304 1305 usage: printf("Usage: do_get hex_tag [dest_file]\n");1306 return -1;1307 1326 } 1308 1327 1309 1328 static int do_put_data(int argc, char **argv) 1310 1329 { 1311 printf("Usage: do_put hex_tag source_file\n" 1312 "or: do_put hex_tag aa:bb:cc\n" 1313 "or: do_put hex_tag \"foobar...\"\n"); 1314 return -1; 1330 return usage(do_put_data); 1315 1331 } 1316 1332 … … 1320 1336 u8 buf[SC_MAX_APDU_BUFFER_SIZE]; 1321 1337 u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; 1322 size_t len, len0, r, ii; 1323 1324 if (argc < 1) { 1325 puts("Usage: apdu [apdu:hex:codes:...]"); 1326 return -1; 1327 } 1328 1329 for (ii = 0, len = 0; ii < (unsigned) argc; ii++) { 1330 len0 = strlen(argv[ii]); 1331 sc_hex_to_bin(argv[ii], buf + len, &len0); 1338 size_t len, r, i; 1339 1340 if (argc < 1) 1341 return usage(do_apdu); 1342 1343 for (i = 0, len = 0; i < (unsigned) argc; i++) { 1344 size_t len0 = strlen(argv[i]); 1345 1346 if ((r = parse_string_or_hexdata(argv[i], buf + len, &len0)) < 0) { 1347 fprintf(stderr, "error parsing %s: %s\n", argv[i], sc_strerror(r)); 1348 return r; 1349 }; 1332 1350 len += len0; 1333 1351 } … … 1343 1361 1344 1362 printf("Sending: "); 1345 for (r = 0; r < len0; r++) 1346 printf("%02X ", buf[r]); 1363 util_hex_dump(stdout, buf, len, " "); 1347 1364 printf("\n"); 1348 1365 r = sc_transmit_apdu(card, &apdu); … … 1368 1385 unsigned char *buf = NULL; 1369 1386 1370 if (argc > 1) { 1371 puts("Usage: asn1 [file_id]"); 1372 return -1; 1373 } 1387 if (argc > 1) 1388 return usage(do_asn1); 1374 1389 1375 1390 /* select file */ … … 1429 1444 } 1430 1445 1446 static int do_help(int argc, char **argv) 1447 { 1448 struct command *cmd; 1449 1450 if (argc) 1451 return usage(do_help); 1452 1453 printf("Supported commands:\n"); 1454 for (cmd = cmds; cmd->name; cmd++) { 1455 int len = strlen(cmd->name) + strlen(cmd->args); 1456 printf(" %s %s%*s %s\n", 1457 cmd->name, cmd->args, 1458 (len > 40) ? 0 : (40 - len), "", 1459 cmd->help); 1460 } 1461 return 0; 1462 } 1463 1431 1464 static int do_quit(int argc, char **argv) 1432 1465 { 1433 1466 die(0); 1434 1467 return 0; 1435 }1436 1437 static struct command cmds[] = {1438 { "ls", do_ls, "list all files in the current DF" },1439 { "cd", do_cd, "change to another DF" },1440 { "cat", do_cat, "print the contents of an EF" },1441 { "info", do_info, "display attributes of card file" },1442 { "create", do_create, "create a new EF" },1443 { "delete", do_delete, "remove an EF/DF" },1444 { "rm", do_delete, "remove an EF/DF" },1445 { "verify", do_verify, "present a PIN or key to the card" },1446 { "change", do_change, "change a PIN" },1447 { "unblock", do_unblock, "unblock a PIN" },1448 { "put", do_put, "copy a local file to the card" },1449 { "get", do_get, "copy an EF to a local file" },1450 { "do_get", do_get_data, "get a data object" },1451 { "do_put", do_put_data, "put a data object" },1452 { "mkdir", do_mkdir, "create a DF" },1453 { "erase", do_erase, "erase card" },1454 { "random", do_random, "obtain N random bytes from card" },1455 { "quit", do_quit, "quit this program" },1456 { "exit", do_quit, "quit this program" },1457 { "update_record", do_update_record, "update record" },1458 { "update_binary", do_update_binary, "update binary" },1459 { "debug", do_debug, "set the debug level" },1460 { "apdu", do_apdu, "send a custom apdu command" },1461 { "asn1", do_asn1, "decode an asn1 file" },1462 { NULL, NULL, NULL }1463 };1464 1465 static void usage(void)1466 {1467 struct command *cmd;1468 1469 printf("Supported commands:\n");1470 for (cmd = cmds; cmd->name; cmd++)1471 printf(" %-16s %s\n", cmd->name, cmd->help);1472 1468 } 1473 1469 … … 1619 1615 } 1620 1616 } 1621 1617 1622 1618 r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle); 1623 1619 if (r && r != SC_ERROR_NOT_SUPPORTED) … … 1626 1622 while (1) { 1627 1623 struct command *cmd; 1628 size_t i; 1629 char prompt[40]; 1630 1631 sprintf(prompt, "OpenSC ["); 1632 for (i = 0; i < current_path.len; i++) { 1633 if ((i & 1) == 0 && i && current_path.type != SC_PATH_TYPE_DF_NAME) 1634 sprintf(prompt+strlen(prompt), "/"); 1635 sprintf(prompt+strlen(prompt), "%02X", 1636 current_path.value[i]); 1637 } 1638 sprintf(prompt+strlen(prompt), "]> "); 1624 char prompt[3*SC_MAX_PATH_STRING_SIZE]; 1625 1626 sprintf(prompt, "OpenSC [%s]> ", path_to_filename(¤t_path, '/')); 1639 1627 line = my_readline(prompt); 1640 1628 if (line == NULL) … … 1647 1635 cmd = ambiguous_match(cmds, cargv[0]); 1648 1636 if (cmd == NULL) { 1649 usage();1637 do_help(0, NULL); 1650 1638 } else { 1651 1639 cmd->func(cargc-1, cargv+1); … … 1654 1642 end: 1655 1643 die(err); 1656 1644 1657 1645 return 0; /* not reached */ 1658 1646 } -
src/tools/opensc-tool.c
r1cdb3fa r8780ddb 333 333 break; 334 334 case SC_FILE_TYPE_DF: 335 tmps = " DF";335 tmps = "DF"; 336 336 break; 337 337 default: … … 339 339 break; 340 340 } 341 printf("type: % -3s, ", tmps);341 printf("type: %s, ", tmps); 342 342 if (file->type != SC_FILE_TYPE_DF) { 343 343 const id2str_t ef_type_name[] = { 344 { SC_FILE_EF_TRANSPARENT, "transp nt"},345 { SC_FILE_EF_LINEAR_FIXED, "lin rfix"},346 { SC_FILE_EF_LINEAR_FIXED_TLV, "lin rfix(TLV)"},347 { SC_FILE_EF_LINEAR_VARIABLE, "lin var" },348 { SC_FILE_EF_LINEAR_VARIABLE_TLV, "lin var(TLV)"},349 { SC_FILE_EF_CYCLIC, " lincyc"},350 { SC_FILE_EF_CYCLIC_TLV, " lincyc(TLV)"},344 { SC_FILE_EF_TRANSPARENT, "transparent" }, 345 { SC_FILE_EF_LINEAR_FIXED, "linear-fixed" }, 346 { SC_FILE_EF_LINEAR_FIXED_TLV, "linear-fixed (TLV)" }, 347 { SC_FILE_EF_LINEAR_VARIABLE, "linear-variable" }, 348 { SC_FILE_EF_LINEAR_VARIABLE_TLV, "linear-variable (TLV)" }, 349 { SC_FILE_EF_CYCLIC, "cyclic" }, 350 { SC_FILE_EF_CYCLIC_TLV, "cyclic (TLV)" }, 351 351 { 0, NULL } 352 352 };
Note: See TracChangeset
for help on using the changeset viewer.
