Changeset 6e70c09 in OpenSC


Ignore:
Timestamp:
06/15/11 08:07:52 (11 months ago)
Author:
martin
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)
Message:

Merge branch 'github-transition' into proposed

Files:
1 added
1 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • Makefile.am

    ra7934b3 rd4e90c1  
    2424Generate-ChangeLog: 
    2525        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; \ 
    3330        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; \ 
    3532                echo > ChangeLog.tmp; \ 
    3633        fi 
  • configure.ac

    r0dcab4a rd4e90c1  
    66define([PACKAGE_VERSION_MINOR], [12]) 
    77define([PACKAGE_VERSION_FIX], [2]) 
    8 define([PACKAGE_SUFFIX], [-svn]) 
     8define([PACKAGE_SUFFIX], [-pre1]) 
    99 
    1010AC_INIT([opensc],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX]) 
     
    193193) 
    194194 
    195 dnl These required for svn checkout 
    196 AC_ARG_VAR([SVN], [subversion utility]) 
     195dnl These required for repository checkout 
    197196AC_ARG_VAR([XSLTPROC], [xsltproc utility]) 
    198 AC_CHECK_PROGS([SVN],[svn]) 
     197AC_ARG_VAR([git], [git]) 
    199198AC_CHECK_PROGS([XSLTPROC],[xsltproc]) 
     199AC_CHECK_PROGS([GIT],[git]) 
    200200 
    201201AC_MSG_CHECKING([xsl-stylesheets]) 
     
    491491if test "${enable_man}" = "yes" -o "${enable_doc}" = "yes"; then 
    492492        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]) 
    494494        test "${xslstylesheetsdir}" != "no" || AC_MSG_ERROR([Missing xslstylesheetsdir]) 
    495495        AC_MSG_RESULT([ok]) 
  • doc/Makefile.am

    r08c111a rd4e90c1  
    11MAINTAINERCLEANFILES = $(srcdir)/Makefile.in 
    22 
    3 dist_noinst_SCRIPTS = svn2cl.xsl html.xsl man.xsl 
     3dist_noinst_SCRIPTS = html.xsl man.xsl 
    44dist_noinst_DATA = $(srcdir)/tools/*.xml api.css 
    55if ENABLE_DOC 
  • src/libopensc/card-openpgp.c

    rbbcb867 r4939432  
    123123static int              pgp_get_blob(sc_card_t *card, struct blob *blob, 
    124124                                 unsigned int id, struct blob **ret); 
    125 static struct blob *    pgp_new_blob(struct blob *, unsigned int, int, 
    126                                 struct do_info *); 
     125static struct blob *    pgp_new_blob(sc_card_t *, struct blob *, unsigned int, sc_file_t *); 
    127126static void             pgp_free_blob(struct blob *); 
    128127static int              pgp_get_pubkey(sc_card_t *, unsigned int, 
     
    162161        { 0x00e1, CONSTRUCTED, READ_NEVER  | WRITE_PIN3,  NULL,               sc_put_data }, 
    163162        { 0x00e2, CONSTRUCTED, READ_NEVER  | WRITE_PIN3,  NULL,               sc_put_data }, 
    164         { 0x00ff, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data,        NULL        }, 
    165163        { 0x0101, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  sc_get_data,        sc_put_data }, 
    166164        { 0x0102, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  sc_get_data,        sc_put_data }, 
    167165        { 0x0103, SIMPLE,      READ_PIN1   | WRITE_PIN1,  sc_get_data,        sc_put_data }, 
    168166        { 0x0104, SIMPLE,      READ_PIN3   | WRITE_PIN3,  sc_get_data,        sc_put_data }, 
     167        { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL,               NULL        }, 
    169168        { 0x5f2d, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  NULL,               sc_put_data }, 
    170169        { 0x5f35, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  NULL,               sc_put_data }, 
     
    217216        { 0x0103, SIMPLE,      READ_PIN1   | WRITE_PIN1,  sc_get_data,        sc_put_data }, 
    218217        { 0x0104, SIMPLE,      READ_PIN3   | WRITE_PIN3,  sc_get_data,        sc_put_data }, 
     218        { 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL,               NULL        }, 
    219219        { 0x5f2d, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  NULL,               sc_put_data }, 
    220220        { 0x5f35, SIMPLE,      READ_ALWAYS | WRITE_PIN3,  NULL,               sc_put_data }, 
     
    277277        card->drv_data = priv; 
    278278 
    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  
    285279        card->cla = 0x00; 
    286280 
     
    310304        } 
    311305 
     306        /* change file path to MF for re-use in MF */ 
    312307        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        } 
    318315 
    319316        /* select MF */ 
     
    324321                if (((info->access & READ_MASK) == READ_ALWAYS) && 
    325322                    (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 
    327325                        /* 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        } 
    339332 
    340333        /* get card_features from ATR & DOs */ 
     
    401394 
    402395                /* get supported algorithms & key lengths from "algorithm attributes" DOs */ 
    403                 for (i = 0x00c1; i < 0x0c3; i++) { 
     396                for (i = 0x00c1; i <= 0x00c3; i++) { 
    404397                        unsigned long flags; 
    405398 
     
    476469/* internal: append a blob to the list of children of a given parent blob */ 
    477470static 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) { 
     471pgp_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; 
    485490                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                } 
    498519        } 
    499520 
     
    507528{ 
    508529        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 
    509540                if (blob->file) 
    510541                        sc_file_free(blob->file); 
     
    584615        while ((int) blob->len > (in - blob->data)) { 
    585616                unsigned int    cla, tag, tmptag; 
    586                 unsigned int    type = SC_FILE_TYPE_WORKING_EF; 
    587617                size_t          len; 
    588618                const u8        *data = in; 
     
    597627                } 
    598628 
    599                 /* create fake file system hierarchy by 
    600                  * using constructed DOs as DF */ 
    601                 if (cla & SC_ASN1_TAG_CONSTRUCTED) 
    602                         type = SC_FILE_TYPE_DF; 
    603  
    604629                /* undo ASN1's split of tag & class */ 
    605630                for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) { 
     
    608633                tag |= cla; 
    609634 
    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) 
    611638                        return SC_ERROR_OUT_OF_MEMORY; 
    612639                pgp_set_blob(new, data, len); 
     
    710737                LOG_FUNC_RETURN(card->ctx, r); 
    711738 
    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                } 
    714747        } 
    715748 
  • src/libopensc/internal-winscard.h

    r19da5d8 r3b63bf3  
    173173#define FEATURE_GET_TLV_PROPERTIES       0x12 
    174174#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 
    175186 
    176187/* structures used (but not defined) in PCSC Part 10: 
  • src/libopensc/reader-pcsc.c

    r44cf3d0 r75524a5  
    8787        DWORD pin_properties_ioctl; 
    8888 
     89        DWORD get_tlv_properties; 
     90 
    8991        int locked; 
    9092}; 
     
    790792                } else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) { 
    791793                        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); 
    792796                } else { 
    793797                        sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Reader feature %02x is not supported", pcsc_tlv[i].tag); 
     
    10301034        unsigned int num_watch; 
    10311035        int r = SC_ERROR_INTERNAL; 
     1036        DWORD dwtimeout; 
    10321037 
    10331038        SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); 
     
    11681173                /* Set the timeout if caller wants to time out */ 
    11691174                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); 
    11741181 
    11751182                if (rv == (LONG) SCARD_E_CANCELLED) { 
     
    14281435} 
    14291436 
     1437/* Find a given PCSC v2 part 10 property */ 
     1438static int 
     1439part10_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 */ 
     1484static int 
     1485part10_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 
    14301522/* Do the PIN command */ 
    14311523static int 
     
    14581550                        return SC_ERROR_NOT_SUPPORTED; 
    14591551                } 
     1552                part10_check_pin_min_max(reader, data); 
    14601553                r = part10_build_verify_pin_block(reader, sbuf, &scount, data); 
    14611554                ioctl = priv->verify_ioctl ? priv->verify_ioctl : priv->verify_ioctl_start; 
     
    14671560                        return SC_ERROR_NOT_SUPPORTED; 
    14681561                } 
     1562                part10_check_pin_min_max(reader, data); 
    14691563                r = part10_build_modify_pin_block(reader, sbuf, &scount, data); 
    14701564                ioctl = priv->modify_ioctl ? priv->modify_ioctl : priv->modify_ioctl_start; 
  • src/pkcs11/opensc-pkcs11.exports

    r0a809dd r5a23069  
    1 C_CancelFunction 
    2 C_CloseAllSessions 
    3 C_CloseSession 
    4 C_CopyObject 
    5 C_CreateObject 
    6 C_Decrypt 
    7 C_DecryptDigestUpdate 
    8 C_DecryptFinal 
    9 C_DecryptInit 
    10 C_DecryptUpdate 
    11 C_DecryptVerifyUpdate 
    12 C_DeriveKey 
    13 C_DestroyObject 
    14 C_Digest 
    15 C_DigestEncryptUpdate 
    16 C_DigestFinal 
    17 C_DigestInit 
    18 C_DigestKey 
    19 C_DigestUpdate 
    20 C_Encrypt 
    21 C_EncryptFinal 
    22 C_EncryptInit 
    23 C_EncryptUpdate 
    24 C_Finalize 
    25 C_FindObjects 
    26 C_FindObjectsFinal 
    27 C_FindObjectsInit 
    28 C_GenerateKey 
    29 C_GenerateKeyPair 
    30 C_GenerateRandom 
    31 C_GetAttributeValue 
    321C_GetFunctionList 
    33 C_GetFunctionStatus 
    34 C_GetInfo 
    35 C_GetMechanismInfo 
    36 C_GetMechanismList 
    37 C_GetObjectSize 
    38 C_GetOperationState 
    39 C_GetSessionInfo 
    40 C_GetSlotInfo 
    41 C_GetSlotList 
    42 C_GetTokenInfo 
    43 C_InitPIN 
    44 C_InitToken 
    45 C_Initialize 
    46 C_Login 
    47 C_Logout 
    48 C_OpenSession 
    49 C_SeedRandom 
    50 C_SetAttributeValue 
    51 C_SetOperationState 
    52 C_SetPIN 
    53 C_Sign 
    54 C_SignEncryptUpdate 
    55 C_SignFinal 
    56 C_SignInit 
    57 C_SignRecover 
    58 C_SignRecoverInit 
    59 C_SignUpdate 
    60 C_UnwrapKey 
    61 C_Verify 
    62 C_VerifyFinal 
    63 C_VerifyInit 
    64 C_VerifyRecover 
    65 C_VerifyRecoverInit 
    66 C_VerifyUpdate 
    67 C_WaitForSlotEvent 
    68 C_WrapKey 
  • src/pkcs15init/pkcs15-lib.c

    rd888b3f r9027279  
    10661066} 
    10671067 
    1068 int 
     1068static int 
    10691069sc_pkcs15init_encode_prvkey_content(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *prvkey, 
    10701070                struct sc_pkcs15_object *object) 
  • src/tools/opensc-explorer.c

    r661cc0d r2faad42  
    3838#define DIM(v) (sizeof(v)/sizeof((v)[0])) 
    3939 
     40/* type for associations of IDs to names */ 
     41typedef struct _id2str { 
     42        unsigned int id; 
     43        const char *str; 
     44} id2str_t; 
     45 
    4046static const char *app_name = "opensc-explorer"; 
    4147 
     
    6672}; 
    6773 
    68 static size_t hex2binary(u8 *out, size_t outlen, const char *in); 
     74 
     75/* declare functions called by user commands */ 
     76static int do_ls(int argc, char **argv); 
     77static int do_cd(int argc, char **argv); 
     78static int do_cat(int argc, char **argv); 
     79static int do_info(int argc, char **argv); 
     80static int do_create(int argc, char **argv); 
     81static int do_mkdir(int argc, char **argv); 
     82static int do_delete(int argc, char **argv); 
     83static int do_verify(int argc, char **argv); 
     84static int do_change(int argc, char **argv); 
     85static int do_unblock(int argc, char **argv); 
     86static int do_get(int argc, char **argv); 
     87static int do_update_binary(int argc, char **argv); 
     88static int do_update_record(int argc, char **argv); 
     89static int do_put(int argc, char **argv); 
     90static int do_debug(int argc, char **argv); 
     91static int do_erase(int argc, char **argv); 
     92static int do_random(int argc, char **argv); 
     93static int do_get_data(int argc, char **argv); 
     94static int do_put_data(int argc, char **argv); 
     95static int do_apdu(int argc, char **argv); 
     96static int do_asn1(int argc, char **argv); 
     97static int do_help(int argc, char **argv); 
     98static int do_quit(int argc, char **argv); 
     99 
    69100 
    70101struct command { 
     102        int             (*func)(int, char **); 
    71103        const char *    name; 
    72         int             (*func)(int, char **); 
     104        const char *    args; 
    73105        const char *    help; 
    74106}; 
     107 
     108static 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 
     188static 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 
     203static 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 
     226static 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} 
    75235 
    76236static void die(int ret) 
     
    131291                /* DF aid */ 
    132292                const char *p = arg + strlen("aid:"); 
    133                 path->len  = hex2binary(path->value, sizeof(path->value), p); 
     293                int r; 
     294 
    134295                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                } 
    135301        } else { 
    136302                /* file id */ 
    137303                unsigned int buf[2]; 
    138304                u8 cbuf[2]; 
    139          
     305 
    140306                if (strlen(arg) != 4) { 
    141307                        printf("Wrong ID length.\n"); 
     
    151317                        path->len = 2; 
    152318                        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; 
    157320                } else { 
    158321                        *path = current_path; 
     
    173336        } 
    174337 
    175         return 0;        
     338        return 0; 
    176339} 
    177340 
     
    210373 
    211374        if (argc) 
    212                 goto usage; 
     375                return usage(do_ls); 
     376 
    213377        r = sc_list_files(card, buf, sizeof(buf)); 
    214378        if (r < 0) { 
     
    231395                        } 
    232396                } 
    233                          
     397 
    234398                r = sc_select_file(card, &path, &file); 
    235399                if (r) { 
     
    245409        } 
    246410        return 0; 
    247 usage: 
    248         puts("Usage: ls"); 
    249         return -1; 
    250411} 
    251412 
     
    257418 
    258419        if (argc != 1) 
    259                 goto usage; 
     420                return usage(do_cd); 
     421 
    260422        if (strcmp(argv[0], "..") == 0) { 
    261423                path = current_path; 
     
    284446        } 
    285447        if (arg_to_path(argv[0], &path, 0) != 0)  
    286                 goto usage; 
     448                return usage(do_cd); 
    287449 
    288450        r = sc_select_file(card, &path, &file); 
     
    303465 
    304466        return 0; 
    305 usage: 
    306         puts("Usage: cd <file_id>|aid:<DF name>"); 
    307         return -1; 
    308467} 
    309468 
     
    314473        size_t count; 
    315474        int r; 
    316          
     475 
    317476        count = file->size; 
    318477        while (count) { 
     
    365524 
    366525        if (argc > 1) 
    367                 goto usage; 
     526                return usage(do_cat); 
     527 
    368528        if (!argc) { 
    369529                path = current_path; 
     
    386546                        if ((sfi < 1) || (sfi > 30)) { 
    387547                                printf("Invalid SFI: %s\n", sfi_n); 
    388                                 goto usage; 
     548                                return usage(do_cat); 
    389549                        } 
    390550                } else { 
    391551                        if (arg_to_path(argv[0], &path, 0) != 0) 
    392                                 goto usage; 
     552                                return usage(do_cat); 
     553 
    393554                        r = sc_select_file(card, &path, &file); 
    394555                        if (r) { 
     
    408569        else 
    409570                read_and_print_record_file(file, sfi); 
    410          
     571 
    411572        err = 0; 
    412  
    413573err: 
    414574        if (not_current) { 
    415                 if (file != NULL) { 
     575                if (file != NULL) 
    416576                        sc_file_free(file); 
    417                 } 
    418577                select_current_path_or_die(); 
    419578        } 
    420579 
    421580        return -err; 
    422 usage: 
    423         puts("Usage: cat [file_id] or"); 
    424         puts("       cat sfi:<sfi_id>"); 
    425         return -1; 
    426581} 
    427582 
     
    433588        const char *st; 
    434589        int r, not_current = 1; 
     590        const id2str_t *ac_ops = NULL; 
    435591 
    436592        if (!argc) { 
     
    440596        } else if (argc == 1) { 
    441597                if (arg_to_path(argv[0], &path, 0) != 0)  
    442                         goto usage; 
     598                        return usage(do_info); 
     599 
    443600                r = sc_select_file(card, &path, &file); 
    444601                if (r) { 
     
    447604                } 
    448605        } else  
    449                 goto usage; 
     606                return usage(do_info); 
    450607 
    451608        switch (file->type) { 
     
    462619        } 
    463620        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); 
    473623 
    474624        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 } 
    478636                }; 
     637 
    479638                if (file->namelen) { 
    480639                        printf("%-15s", "DF name:"); 
     
    482641                        printf("\n"); 
    483642                } 
    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; 
    490645        } 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 } 
    495656                }; 
    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 } 
    508666                }; 
    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 
    517686        if (file->prop_attr_len) { 
    518687                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, " "); 
    521689                printf("\n"); 
    522690        } 
    523691        if (file->sec_attr_len) { 
    524692                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, " "); 
    527694                printf("\n"); 
    528695        } 
     
    533700        } 
    534701        return 0; 
    535  
    536 usage: 
    537         puts("Usage: info [file_id]"); 
    538         return -1; 
    539702} 
    540703 
     
    542705{ 
    543706        int r; 
    544          
     707 
    545708        r = sc_create_file(card, file); 
    546709        if (r) { 
     
    562725 
    563726        if (argc != 2) 
    564                 goto usage; 
     727                return usage(do_create); 
    565728        if (arg_to_path(argv[0], &path, 1) != 0) 
    566                 goto usage; 
     729                return usage(do_create); 
    567730        /* %z isn't supported everywhere */ 
    568731        if (sscanf(argv[1], "%u", &size) != 1) 
    569                 goto usage; 
     732                return usage(do_create); 
    570733        file = sc_file_new(); 
    571734        file->id = (path.value[0] << 8) | path.value[1]; 
     
    576739        for (op = 0; op < SC_MAX_AC_OPS; op++) 
    577740                sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); 
    578          
     741 
    579742        r = create_file(file); 
    580743        sc_file_free(file); 
    581744        return r; 
    582  usage: 
    583         printf("Usage: create <file_id> <file_size>\n"); 
    584         return -1; 
    585745} 
    586746 
     
    593753 
    594754        if (argc != 2) 
    595                 goto usage; 
     755                return usage(do_mkdir); 
    596756        if (arg_to_path(argv[0], &path, 1) != 0) 
    597                 goto usage; 
     757                return usage(do_mkdir); 
    598758        if (sscanf(argv[1], "%u", &size) != 1) 
    599                 goto usage; 
     759                return usage(do_mkdir); 
    600760        file = sc_file_new(); 
    601761        file->id = (path.value[0] << 8) | path.value[1]; 
     
    609769        sc_file_free(file); 
    610770        return r; 
    611  usage: 
    612         printf("Usage: mkdir <file_id> <df_size>\n"); 
    613         return -1; 
    614771} 
    615772 
     
    620777 
    621778        if (argc != 1) 
    622                 goto usage; 
     779                return usage(do_delete); 
    623780        if (arg_to_path(argv[0], &path, 1) != 0) 
    624                 goto usage; 
     781                return usage(do_delete); 
    625782        if (path.len != 2) 
    626                 goto usage; 
     783                return usage(do_delete); 
    627784        path.type = SC_PATH_TYPE_FILE_ID; 
    628785        r = sc_delete_file(card, &path); 
     
    632789        } 
    633790        return 0; 
    634 usage: 
    635         printf("Usage: delete <file_id>\n"); 
    636         return -1; 
    637791} 
    638792 
    639793static int do_verify(int argc, char **argv) 
    640794{ 
    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,   } 
    650801        }; 
    651802        int r, tries_left = -1; 
    652803        u8 buf[64]; 
    653         const char *s; 
    654804        size_t buflen = sizeof(buf), i; 
    655805        struct sc_pin_cmd_data data; 
     
    662812 
    663813        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; 
    667817                        break; 
    668818                } 
     
    685835                data.pin1.prompt = "Please enter PIN"; 
    686836                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; 
    692837        } else { 
    693                 r = sc_hex_to_bin(argv[1], buf, &buflen);  
     838                r = parse_string_or_hexdata(argv[1], buf, &buflen); 
    694839                if (0 != r) { 
    695840                        printf("Invalid key value.\n"); 
     
    714859        return 0; 
    715860usage: 
    716         printf("Usage: verify <key type><key ref> [<key in hex>]\n"); 
     861        printf("Usage: verify <key type><key ref> [<pin>]\n"); 
    717862        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); 
    720865        printf("Example: verify CHV2 31:32:33:34:00:00:00:00\n"); 
    721866        printf("If key is omitted, card reader's keypad will be used to collect PIN.\n"); 
     
    729874        u8 oldpin[30]; 
    730875        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 
    735879        if (argc < 1 || argc > 3) 
    736880                goto usage; 
     
    743887                goto usage; 
    744888        } 
    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) { 
    762893                        printf("Invalid key value.\n"); 
    763894                        goto usage; 
    764895                } 
    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) { 
    776901                        printf("Invalid key value.\n"); 
    777902                        goto usage; 
     
    808933{ 
    809934        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 
    816940        if (argc < 1 || argc > 3) 
    817941                goto usage; 
     
    824948                goto usage; 
    825949        } 
    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) { 
    839954                        printf("Invalid key value.\n"); 
    840955                        goto usage; 
    841956                } 
    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) { 
    855962                        printf("Invalid key value.\n"); 
    856963                        goto usage; 
    857964                } 
    858  
    859                 newpin = &newpin_buf[0]; 
    860         } 
    861         else   { 
    862                 newpinlen = 0; 
    863                 newpin = NULL; 
    864965        } 
    865966 
    866967        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); 
    869970        if (r) { 
    870971                if (r == SC_ERROR_PIN_CODE_INCORRECT) 
     
    876977        return 0; 
    877978usage: 
    878         printf("Usage: unblock CHV<pin ref> [<puk>] [<new pin>]\n"); 
     979        printf("Usage: unblock CHV<pin ref> [<puk> [<new pin>]]\n"); 
    879980        printf("PUK and PIN values can be hexadecimal, ASCII, empty (\"\") or absent\n"); 
    880981        printf("Examples:\n"); 
     
    897998        sc_path_t path; 
    898999        sc_file_t *file = NULL; 
    899         char fbuf[256], *filename; 
     1000        char *filename; 
    9001001        FILE *outf = NULL; 
    901          
     1002 
    9021003        if (argc < 1 || argc > 2) 
    903                 goto usage; 
     1004                return usage(do_get); 
    9041005        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, '_'); 
    9181009        outf = (strcmp(filename, "-") == 0) 
    9191010                ? stdout 
     
    9581049                       idx, argv[0], filename); 
    9591050        } 
    960          
     1051 
    9611052        err = 0; 
    9621053err: 
     
    9671058        select_current_path_or_die(); 
    9681059        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; 
    10071060} 
    10081061 
     
    10101063{ 
    10111064        u8 buf[240]; 
    1012         int r, err = 1, in_len; 
     1065        size_t buflen = sizeof(buf); 
     1066        int r, err = 1; 
    10131067        int offs; 
    10141068        sc_path_t path; 
    10151069        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); 
    10201073        if (arg_to_path(argv[0], &path, 0) != 0) 
    1021                 goto usage; 
     1074                return usage(do_update_binary); 
    10221075        offs = strtol(argv[1],NULL,10); 
    10231076 
    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 
    10371085        r = sc_select_file(card, &path, &file); 
    10381086        if (r) { 
     
    10451093                goto err; 
    10461094        } 
    1047          
    1048         r = sc_update_binary(card, offs, buf, in_len, 0); 
     1095 
     1096        r = sc_update_binary(card, offs, buf, buflen, 0); 
    10491097        if (r < 0) { 
    10501098                printf("Cannot update %04X; return %i\n", file->id, r); 
     
    10561104 
    10571105        err = 0; 
    1058  
    10591106err: 
    10601107        sc_file_free(file); 
    10611108        select_current_path_or_die(); 
    10621109        return -err; 
    1063 usage: 
    1064         printf("Usage: update <file id> offs <hex value> | <'\"' enclosed string>\n"); 
    1065         return -1; 
    10661110} 
    10671111 
     
    10691113{ 
    10701114        u8 buf[240]; 
     1115        size_t buflen; 
    10711116        int r, i, err = 1; 
    10721117        int rec, offs; 
    10731118        sc_path_t path; 
    10741119        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); 
    10791123        if (arg_to_path(argv[0], &path, 0) != 0) 
    1080                 goto usage; 
     1124                return usage(do_update_record); 
    10811125        rec  = strtol(argv[1],NULL,10); 
    10821126        offs = strtol(argv[2],NULL,10); 
    10831127 
    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]); 
    10861129 
    10871130        r = sc_select_file(card, &path, &file); 
     
    10981141                goto err; 
    10991142        } 
    1100          
     1143 
    11011144        r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); 
    11021145        if (r<0)   { 
     
    11051148        } 
    11061149 
    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); 
    11081152        if (!i) { 
    1109                 printf("unable to parse hex value\n"); 
     1153                printf("unable to parse data\n"); 
    11101154                goto err; 
    11111155        } 
     
    11191163        printf("Total of %d bytes written to record %i at %i offset.\n",  
    11201164               i, rec, offs); 
     1165 
    11211166        err = 0; 
    1122  
    11231167err: 
    11241168        sc_file_free(file); 
    11251169        select_current_path_or_die(); 
    11261170        return -err; 
    1127 usage: 
    1128         printf("Usage: update_record <file id> rec_nr rec_offs <hex value>\n"); 
    1129         return -1; 
    11301171} 
    11311172 
     
    11431184 
    11441185        if (argc < 1 || argc > 2) 
    1145                 goto usage; 
     1186                return usage(do_put); 
    11461187        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, '_'); 
    11541191        outf = fopen(filename, "rb"); 
    11551192        if (outf == NULL) { 
     
    11881225 
    11891226        err = 0; 
    1190  
    11911227err: 
    1192  
    11931228        if (file) 
    11941229                sc_file_free(file); 
     
    11971232        select_current_path_or_die(); 
    11981233        return -err; 
    1199 usage: 
    1200         printf("Usage: put <file id> [input file]\n"); 
    1201         return -1; 
    12021234} 
    12031235 
     
    12211253 
    12221254 
    1223 static int 
    1224 do_erase(int argc, char **argv) 
     1255static int do_erase(int argc, char **argv) 
    12251256{ 
    12261257        int     r; 
    12271258 
    12281259        if (argc != 0) 
    1229                 goto usage; 
     1260                return usage(do_erase); 
    12301261 
    12311262        r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL); 
     
    12351266        } 
    12361267        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 
     1270static int do_random(int argc, char **argv) 
    12451271{ 
    12461272        unsigned char buffer[128]; 
     
    12481274 
    12491275        if (argc != 1) 
    1250                 goto usage; 
     1276                return usage(do_random); 
    12511277 
    12521278        count = atoi(argv[0]); 
     
    12641290        util_hex_dump_asc(stdout, buffer, count, 0); 
    12651291        return 0; 
    1266  
    1267 usage: 
    1268         printf("Usage: random count\n"); 
    1269         return -1; 
    12701292} 
    12711293 
     
    12781300 
    12791301        if (argc != 1 && argc != 2) 
    1280                 goto usage; 
     1302                return usage(do_get_data); 
    12811303 
    12821304        tag = strtoul(argv[0], NULL, 16); 
     
    13021324 
    13031325        return 0; 
    1304  
    1305 usage:  printf("Usage: do_get hex_tag [dest_file]\n"); 
    1306         return -1; 
    13071326} 
    13081327 
    13091328static int do_put_data(int argc, char **argv) 
    13101329{ 
    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); 
    13151331} 
    13161332 
     
    13201336        u8 buf[SC_MAX_APDU_BUFFER_SIZE]; 
    13211337        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                }; 
    13321350                len += len0; 
    13331351        } 
     
    13431361 
    13441362        printf("Sending: "); 
    1345         for (r = 0; r < len0; r++) 
    1346                 printf("%02X ", buf[r]); 
     1363        util_hex_dump(stdout, buf, len, " "); 
    13471364        printf("\n"); 
    13481365        r = sc_transmit_apdu(card, &apdu); 
     
    13681385        unsigned char *buf = NULL; 
    13691386 
    1370         if (argc > 1) { 
    1371                 puts("Usage: asn1 [file_id]"); 
    1372                 return -1; 
    1373         } 
     1387        if (argc > 1) 
     1388                return usage(do_asn1); 
    13741389 
    13751390        /* select file */ 
     
    14291444} 
    14301445 
     1446static 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 
    14311464static int do_quit(int argc, char **argv) 
    14321465{ 
    14331466        die(0); 
    14341467        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); 
    14721468} 
    14731469 
     
    16191615                } 
    16201616        } 
    1621          
     1617 
    16221618        r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle); 
    16231619        if (r && r != SC_ERROR_NOT_SUPPORTED) 
     
    16261622        while (1) { 
    16271623                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(&current_path, '/')); 
    16391627                line = my_readline(prompt); 
    16401628                if (line == NULL) 
     
    16471635                cmd = ambiguous_match(cmds, cargv[0]); 
    16481636                if (cmd == NULL) { 
    1649                         usage(); 
     1637                        do_help(0, NULL); 
    16501638                } else { 
    16511639                        cmd->func(cargc-1, cargv+1); 
     
    16541642end: 
    16551643        die(err); 
    1656          
     1644 
    16571645        return 0; /* not reached */ 
    16581646} 
  • src/tools/opensc-tool.c

    r1cdb3fa r8780ddb  
    333333                break; 
    334334        case SC_FILE_TYPE_DF: 
    335                 tmps = " DF"; 
     335                tmps = "DF"; 
    336336                break; 
    337337        default: 
     
    339339                break; 
    340340        } 
    341         printf("type: %-3s, ", tmps); 
     341        printf("type: %s, ", tmps); 
    342342        if (file->type != SC_FILE_TYPE_DF) { 
    343343                const id2str_t ef_type_name[] = { 
    344                         { SC_FILE_EF_TRANSPARENT,         "transpnt"     }, 
    345                         { SC_FILE_EF_LINEAR_FIXED,        "linrfix"      }, 
    346                         { SC_FILE_EF_LINEAR_FIXED_TLV,    "linrfix(TLV)" }, 
    347                         { SC_FILE_EF_LINEAR_VARIABLE,     "linvar"       }, 
    348                         { SC_FILE_EF_LINEAR_VARIABLE_TLV, "linvar(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)"          }, 
    351351                        { 0, NULL } 
    352352                }; 
Note: See TracChangeset for help on using the changeset viewer.