[BACK]Return to cyberflex.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sectok

Annotation of src/usr.bin/sectok/cyberflex.c, Revision 1.22

1.22    ! rees        1: /* $Id: cyberflex.c,v 1.9 2002/03/19 18:13:42 rees Exp $ */
1.1       rees        2:
                      3: /*
                      4: copyright 1999, 2000
                      5: the regents of the university of michigan
                      6: all rights reserved
                      7:
                      8: permission is granted to use, copy, create derivative works
                      9: and redistribute this software and such derivative works
                     10: for any purpose, so long as the name of the university of
                     11: michigan is not used in any advertising or publicity
                     12: pertaining to the use or distribution of this software
                     13: without specific, written prior authorization.  if the
                     14: above copyright notice or any other identification of the
                     15: university of michigan is included in any copy of any
                     16: portion of this software, then the disclaimer below must
                     17: also be included.
                     18:
                     19: this software is provided as is, without representation
                     20: from the university of michigan as to its fitness for any
                     21: purpose, and without warranty by the university of
                     22: michigan of any kind, either express or implied, including
                     23: without limitation the implied warranties of
                     24: merchantability and fitness for a particular purpose. the
                     25: regents of the university of michigan shall not be liable
                     26: for any damages, including special, indirect, incidental, or
                     27: consequential damages, with respect to any claim arising
                     28: out of or in connection with the use of the software, even
                     29: if it has been or is hereafter advised of the possibility of
                     30: such damages.
                     31: */
                     32:
1.18      rees       33: #ifndef __palmos__
1.5       rees       34: #include <sys/types.h>
1.1       rees       35: #include <unistd.h>
                     36: #include <stdlib.h>
                     37: #include <stdio.h>
                     38: #include <signal.h>
                     39: #include <string.h>
                     40: #include <fcntl.h>
1.17      rees       41: #include <des.h>
1.1       rees       42: #ifdef __linux
1.17      rees       43: #include <sha.h>
                     44: #define SHA1_CTX SHA_CTX
                     45: #define SHA1Init SHA1_Init
                     46: #define SHA1Update SHA1_Update
                     47: #define SHA1Final SHA1_Final
1.1       rees       48: #else /* __linux */
1.17      rees       49: #include <sha1.h>
1.1       rees       50: #endif
1.18      rees       51: #else
                     52: #pragma pack(2)
                     53: #include <Common.h>
                     54: #include <System/SysAll.h>
                     55: #include <System/Unix/sys_types.h>
                     56: #include <System/Unix/unix_stdio.h>
                     57: #include <System/Unix/unix_stdlib.h>
                     58: #include <System/Unix/unix_string.h>
                     59: #include <UI/UIAll.h>
                     60: #include "getopt.h"
                     61: #include "field.h"
                     62: #define NO_SHA
                     63: #endif
1.1       rees       64: #include <sectok.h>
                     65:
                     66: #include "sc.h"
                     67:
                     68: #ifdef __sun
                     69: #define des_set_key(key, schedule) des_key_sched(key, schedule)
                     70: #endif
                     71:
                     72: #define MAX_KEY_FILE_SIZE 1024
                     73: #define NUM_RSA_KEY_ELEMENTS 5
                     74: #define RSA_BIT_LEN 1024
                     75: #define KEY_FILE_HEADER_SIZE 8
                     76:
1.12      rees       77: #define myisprint(x) ((x) >= '!' && (x) <= 'z')
                     78:
1.1       rees       79: static unsigned char key_fid[] = {0x00, 0x11};
                     80: static unsigned char DFLTATR[] = {0x81, 0x10, 0x06, 0x01};
1.5       rees       81: static unsigned char DFLTAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
1.7       rees       82: static unsigned char AUT0[20];
1.1       rees       83:
1.4       rees       84: int aut0_vfyd;
                     85:
1.18      rees       86: static void print_acl(int isdir, unsigned char *acl);
                     87:
                     88: #ifndef __palmos__
1.1       rees       89: /* default signed applet key of Cyberflex Access */
                     90: static des_cblock app_key = {0x6A, 0x21, 0x36, 0xF5, 0xD8, 0x0C, 0x47, 0x83};
1.18      rees       91: #endif
1.9       rees       92:
1.5       rees       93: static int
1.14      rees       94: get_AUT0(int ac, char *av[], char *prompt, int confirm, unsigned char *digest)
1.5       rees       95: {
1.18      rees       96: #ifdef NO_SHA
                     97:     memcpy(digest, DFLTAUT0, sizeof DFLTAUT0);
                     98: #else
1.5       rees       99:     int i, dflag = 0, xflag = 0;
                    100:     SHA1_CTX ctx;
1.14      rees      101:     char *s, *s2;
1.5       rees      102:
                    103:     optind = optreset = 1;
                    104:     opterr = 0;
                    105:
1.10      rees      106:     while ((i = getopt(ac, av, "dk:x:")) != -1) {
1.5       rees      107:        switch (i) {
                    108:        case 'd':
1.18      rees      109:            memcpy(digest, DFLTAUT0, sizeof DFLTAUT0);
1.5       rees      110:            dflag = 1;
                    111:            break;
                    112:        case 'x':
1.11      rees      113:            if (sectok_parse_input(optarg, digest, 8) != 8) {
1.5       rees      114:                printf("AUT0 must be length 8\n");
                    115:                return -1;
                    116:            }
                    117:            xflag = 1;
                    118:            break;
                    119:        }
                    120:     }
                    121:
                    122:     if (!dflag && !xflag) {
                    123:        SHA1Init(&ctx);
1.22    ! rees      124:        /* "-" means DFLTAUT0 */
1.5       rees      125:        s = getpass(prompt);
1.22    ! rees      126:        if (!strcmp(s, "-"))
        !           127:            memcpy(digest, DFLTAUT0, sizeof DFLTAUT0);
        !           128:        else {
        !           129:            if (confirm) {
        !           130:                s2 = strdup(s);
        !           131:                s = getpass("Re-enter passphrase: ");
        !           132:                if (strcmp(s, s2)) {
        !           133:                    printf("passphrase mismatch\n");
        !           134:                    return -1;
        !           135:                }
        !           136:                bzero(s2, strlen(s2));
        !           137:                free(s2);
1.14      rees      138:            }
1.22    ! rees      139:            SHA1Update(&ctx, s, strlen(s));
        !           140:            bzero(s, strlen(s));
        !           141:            SHA1Final(digest, &ctx);
1.14      rees      142:        }
1.5       rees      143:     }
1.18      rees      144: #endif
1.5       rees      145:
                    146:     return 0;
                    147: }
                    148:
1.6       rees      149: int jlogin(int ac, char *av[])
1.4       rees      150: {
1.10      rees      151:     int i, keyno = 0, vflag = 0, sw;
1.4       rees      152:
1.7       rees      153:     if (fd < 0 && reset(0, NULL) < 0)
                    154:        return -1;
                    155:
                    156:     cla = cyberflex_inq_class(fd);
                    157:     if (cla < 0) {
                    158:        printf("can't determine Cyberflex application class\n");
                    159:        return -1;
                    160:     }
1.5       rees      161:
                    162:     optind = optreset = 1;
1.4       rees      163:
1.10      rees      164:     while ((i = getopt(ac, av, "dk:vx:")) != -1) {
1.4       rees      165:        switch (i) {
1.10      rees      166:        case 'k':
                    167:            keyno = atoi(optarg);
                    168:            break;
1.4       rees      169:        case 'v':
                    170:            vflag = 1;
                    171:            break;
                    172:        }
                    173:     }
                    174:
1.14      rees      175:     if (get_AUT0(ac, av, "Enter AUT0 passphrase: ", 0, AUT0) < 0)
1.5       rees      176:        return -1;
                    177:
                    178:     if (vflag) {
1.4       rees      179:        printf("Class %02x\n", cla);
1.5       rees      180:        for (i = 0; i < 8; i++)
                    181:            printf("%02x ", AUT0[i]);
                    182:        printf("\n");
                    183:     }
                    184:
1.10      rees      185:     sectok_apdu(fd, cla, 0x2a, 0, keyno, 8, AUT0, 0, NULL, &sw);
1.4       rees      186:
1.5       rees      187:     if (!sectok_swOK(sw)) {
                    188:        printf("AUT0 failed: %s\n", sectok_get_sw(sw));
                    189:        aut0_vfyd = 0;
                    190:        return -1;
                    191:     }
                    192:     aut0_vfyd = 1;
                    193:     return 0;
1.6       rees      194: }
                    195:
                    196: int jaut(int ac, char *av[])
                    197: {
                    198:     static char *jlav[] = {"login", "-d", NULL};
                    199:
                    200:     return jlogin(2, jlav);
1.4       rees      201: }
                    202:
1.1       rees      203: int jdefault(int ac, char *av[])
                    204: {
                    205:     unsigned char buf[8];
1.4       rees      206:     int i, p1 = 4, sw;
1.1       rees      207:
                    208:     optind = optreset = 1;
                    209:
                    210:     while ((i = getopt(ac, av, "d")) != -1) {
                    211:        switch (i) {
                    212:        case 'd':
                    213:            p1 = 5;
                    214:            break;
                    215:        }
                    216:     }
                    217:
1.7       rees      218:     if (fd < 0 && reset(0, NULL) < 0)
                    219:        return -1;
1.4       rees      220:     if (!aut0_vfyd)
                    221:        jaut(0, NULL);
1.1       rees      222:
1.4       rees      223:     sectok_apdu(fd, cla, 0x08, p1, 0, 0, buf, 0, NULL, &sw);
                    224:     if (!sectok_swOK(sw)) {
1.1       rees      225:        /* error */
1.4       rees      226:        sectok_print_sw(sw);
1.1       rees      227:        return -1;
                    228:     }
                    229:     return 0;
                    230: }
                    231:
                    232: int jatr(int ac, char *av[])
                    233: {
                    234:     unsigned char buf[64];
1.4       rees      235:     int n = 0, sw;
1.1       rees      236:
                    237:     buf[n++] = 0x90;
                    238:     buf[n++] = 0x94;           /* TA1 */
                    239:     buf[n++] = 0x40;           /* TD1 */
                    240:     buf[n++] = 0x28;           /* TC2 (WWT=4sec) */
1.12      rees      241:     if (ac > 1) {
1.1       rees      242:        /* set historical bytes from command line */
1.11      rees      243:        n += sectok_parse_input(av[1], &buf[n], 15);
1.1       rees      244:     } else {
                    245:        /* no historical bytes given, use default */
1.18      rees      246:        memcpy(&buf[n], DFLTATR, sizeof DFLTATR);
1.1       rees      247:        n += sizeof DFLTATR;
                    248:     }
                    249:     buf[0] |= ((n - 2) & 0xf);
1.11      rees      250:
                    251:     if (fd < 0 && reset(0, NULL) < 0)
                    252:        return -1;
                    253:
1.4       rees      254:     sectok_apdu(fd, cla, 0xfa, 0, 0, n, buf, 0, NULL, &sw);
                    255:     if (!sectok_swOK(sw)) {
1.1       rees      256:        /* error */
1.4       rees      257:        sectok_print_sw(sw);
1.1       rees      258:        return -1;
                    259:     }
                    260:     return 0;
                    261: }
                    262:
                    263: int jdata(int ac, char *av[])
                    264: {
                    265:     unsigned char buf[32];
1.4       rees      266:     int i, sw;
1.1       rees      267:
1.7       rees      268:     if (fd < 0 && reset(0, NULL) < 0)
                    269:        return -1;
1.1       rees      270:
1.12      rees      271:     cla = cyberflex_inq_class(fd);
                    272:     if (cla < 0) {
                    273:        printf("can't determine Cyberflex application class\n");
                    274:        return -1;
                    275:     }
                    276:
1.4       rees      277:     sectok_apdu(fd, cla, 0xca, 0, 1, 0, NULL, 0x16, buf, &sw);
                    278:     if (sectok_swOK(sw)) {
1.1       rees      279:        printf("serno ");
                    280:        for (i = 0; i < 6; i++)
                    281:            printf("%02x ", buf[i]);
1.10      rees      282:        if (buf[20] == 0x13) {
                    283:            /* these cards have a different format */
                    284:            printf("scrambled sver %d.%02d ", buf[19], buf[20]);
                    285:            if (buf[21] == 0x0c)
                    286:                printf("augmented ");
                    287:            else if (buf[21] == 0x0b)
                    288:                ;
                    289:            else
                    290:                printf("unknown ");
                    291:            printf("crypto %5.5s class %02x\n", &buf[14], cyberflex_inq_class(fd));
                    292:        } else {
                    293:            printf("batch %02x sver %d.%02d ", buf[6], buf[7], buf[8]);
                    294:            if (buf[9] == 0x0c)
                    295:                printf("augmented ");
                    296:            else if (buf[9] == 0x0b)
                    297:                ;
                    298:            else
                    299:                printf("unknown ");
                    300:            printf("crypto %9.9s class %02x\n", &buf[10], buf[19]);
                    301:        }
1.1       rees      302:     } else {
                    303:        /* error */
1.4       rees      304:        sectok_print_sw(sw);
1.1       rees      305:     }
                    306:     return 0;
                    307: }
                    308:
                    309: #define JDIRSIZE 40
                    310:
1.8       rees      311: static char *apptype[] = {
                    312:     "?",
                    313:     "applet",
                    314:     "app",
                    315:     "app/applet",
                    316: };
                    317:
                    318: static char *appstat[] = {
                    319:     "?",
                    320:     "created",
                    321:     "installed",
                    322:     "registered",
                    323: };
                    324:
                    325: static char *filestruct[] = {
                    326:     "binary",
                    327:     "fixed rec",
                    328:     "variable rec",
                    329:     "cyclic",
                    330:     "program",
                    331: };
                    332:
                    333: static char *principals[] = {
                    334:     "world", "CHV1", "CHV2", "AUT0", "AUT1", "AUT2", "AUT3", "AUT4"
                    335: };
                    336:
                    337: static char *f_rights[] = {
                    338:     "r", "w", "x/a", "inval", "rehab", NULL, "dec", "inc"
                    339: };
                    340:
                    341: static char *d_rights[] = {
                    342:     "l", "d", "a", NULL, NULL, "i", "manage", NULL
                    343: };
                    344:
1.9       rees      345: static void
                    346: print_acl(int isdir, unsigned char *acl)
                    347: {
                    348:     int i, j;
                    349:     char *as;
                    350:
                    351:     for (i = 0; i < 8; i++) {
                    352:        if (acl[i]) {
                    353:            printf(" %s: ", principals[i]);
                    354:            for (j = 0; j < 8; j++)
                    355:                if (acl[i] & (1 << j)) {
                    356:                    as = isdir ? d_rights[j] : f_rights[j];
                    357:                    if (as)
                    358:                        printf("%s ", as);
                    359:                }
                    360:            printf("\n");
                    361:        }
                    362:     }
                    363: }
                    364:
1.12      rees      365: void
                    366: sectok_fmt_aidname(char *aidname, int aidlen, unsigned char *aid)
                    367: {
                    368:     int i, istext = 1;
                    369:
1.13      rees      370:     for (i = 1; i < aidlen; i++)
1.12      rees      371:        if (!myisprint(aid[i])) {
                    372:            istext = 0;
                    373:            break;
                    374:        }
                    375:     if (istext) {
1.18      rees      376:        memcpy(aidname, aid, aidlen);
1.12      rees      377:        aidname[aidlen] = '\0';
1.13      rees      378:        if (aid[0] == 0xfc)
                    379:            aidname[0] = '#';
1.12      rees      380:     } else {
                    381:        for (i = 0; i < aidlen; i++)
                    382:            sprintf(&aidname[i * 2], "%02x", aid[i]);
                    383:     }
                    384: }
                    385:
1.1       rees      386: int ls(int ac, char *av[])
                    387: {
1.21      rees      388:     int i, p2, fid, lflag = 0, buflen, sw;
1.8       rees      389:     int isdir, fsize;
1.12      rees      390:     char ftype[32], fname[6], aidname[34];
1.1       rees      391:     unsigned char buf[JDIRSIZE];
                    392:
1.8       rees      393:     optind = optreset = 1;
                    394:
1.9       rees      395:     while ((i = getopt(ac, av, "l")) != -1) {
1.8       rees      396:        switch (i) {
                    397:        case 'l':
                    398:            lflag = 1;
                    399:            break;
                    400:        }
                    401:     }
                    402:
1.7       rees      403:     if (fd < 0 && reset(0, NULL) < 0)
                    404:        return -1;
1.1       rees      405:
                    406:     for (p2 = 0; ; p2++) {
1.12      rees      407:        buflen = sectok_apdu(fd, cla, 0xa8, 0, p2, 0, NULL, JDIRSIZE, buf, &sw);
1.4       rees      408:        if (!sectok_swOK(sw))
1.1       rees      409:            break;
1.21      rees      410:
                    411:        /* Don't show reserved fids */
                    412:        fid = sectok_mksw(buf[4], buf[5]);
                    413:        if (fid == 0x3f11 || fid == 0x3fff || fid == 0xffff)
1.1       rees      414:            continue;
1.8       rees      415:
                    416:        /* Format name */
1.15      rees      417:        sectok_fmt_fid(fname, &buf[4]);
1.8       rees      418:
                    419:        /* Format size */
                    420:        fsize = (buf[2] << 8) | buf[3];
                    421:
                    422:        /* Format file type */
                    423:        isdir = 0;
1.12      rees      424:        aidname[0] = '\0';
1.8       rees      425:        if (buf[6] == 1) {
1.1       rees      426:            /* root */
                    427:            sprintf(ftype, "root");
1.8       rees      428:            isdir = 1;
                    429:        } else if (buf[6] == 2) {
1.1       rees      430:            /* DF */
1.12      rees      431:            if (buf[12] == 27) {
                    432:                /* application */
1.1       rees      433:                sprintf(ftype, "%s %s", appstat[buf[10]], apptype[buf[9]]);
1.12      rees      434:                if (buflen > 23 && buf[23]) {
                    435:                    aidname[0] = ' ';
                    436:                    sectok_fmt_aidname(&aidname[1], buf[23], &buf[24]);
                    437:                }
                    438:            } else
1.1       rees      439:                sprintf(ftype, "directory");
1.9       rees      440:            isdir = 1;
1.8       rees      441:        } else if (buf[6] == 4) {
1.1       rees      442:            /* EF */
                    443:            sprintf(ftype, "%s", filestruct[buf[13]]);
1.8       rees      444:        }
                    445:
                    446:        if (!lflag)
                    447:            printf("%-4s\n", fname);
                    448:        else
1.12      rees      449:            printf("%-4s %5d %s%s\n", fname, fsize, ftype, aidname);
1.9       rees      450:     }
                    451:     return 0;
                    452: }
                    453:
                    454: int acl(int ac, char *av[])
                    455: {
1.16      rees      456:     int i, j, xflag = 0, isdir, prno, rt, sw;
1.9       rees      457:     unsigned char fid[2], buf[256], acl[8];
1.16      rees      458:     char *prin;
1.9       rees      459:
1.16      rees      460:     optind = optreset = 1;
                    461:
                    462:     while ((i = getopt(ac, av, "x")) != -1) {
                    463:        switch (i) {
                    464:        case 'x':
                    465:            xflag = 1;
                    466:            break;
                    467:        }
                    468:     }
                    469:
                    470:     if (ac - optind < 1) {
                    471:        printf("usage: acl [ -x ] fid [ principal: r1 r2 ... ]\n");
1.9       rees      472:        return -1;
                    473:     }
                    474:
                    475:     /* Select the fid */
1.16      rees      476:     sectok_parse_fname(av[optind++], fid);
1.9       rees      477:     sectok_apdu(fd, cla, 0xa4, 0, 0, 2, fid, sizeof buf, buf, &sw);
                    478:     if (!sectok_swOK(sw)) {
                    479:        printf("Select: %s\n", sectok_get_sw(sw));
                    480:        return -1;
                    481:     }
                    482:
                    483:     isdir = (buf[6] == 1 || buf[6] == 2);
1.8       rees      484:
1.9       rees      485:     /* Get current acl */
                    486:     sectok_apdu(fd, cla, 0xfe, 0, 0, 0, NULL, 8, acl, &sw);
                    487:     if (!sectok_swOK(sw)) {
                    488:        printf("GetFileACL: %s\n", sectok_get_sw(sw));
                    489:        return -1;
                    490:     }
                    491:
1.16      rees      492:     if (ac - optind < 1) {
1.9       rees      493:        /* No acl given; print acl and exit */
1.16      rees      494:        if (xflag) {
                    495:            for (i = 0; i < 8; i++)
                    496:                printf("%02x ", acl[i]);
                    497:            printf("\n");
                    498:        } else
                    499:            print_acl(isdir, acl);
1.9       rees      500:        return 0;
                    501:     }
                    502:
1.16      rees      503:     prin = av[optind++];
                    504:
1.9       rees      505:     /* strip trailing ':' */
1.16      rees      506:     prin[strlen(prin) - 1] = '\0';
1.9       rees      507:
                    508:     /* Find principal */
                    509:     for (prno = 0; prno < 8; prno++)
1.16      rees      510:        if (!strcasecmp(prin, principals[prno]))
1.9       rees      511:            break;
                    512:     if (prno >= 8) {
1.16      rees      513:        printf("unknown principal \"%s\"\n", prin);
1.9       rees      514:        return -1;
                    515:     }
                    516:
                    517:     /* Parse new rights */
                    518:     rt = 0;
1.16      rees      519:     for (i = optind; i < optind + 8 && i < ac; i++) {
                    520:        for (j = 0; j < 8; j++) {
1.9       rees      521:            if ((d_rights[j] && !strcasecmp(av[i], d_rights[j]))
                    522:                || (f_rights[j] && !strcasecmp(av[i], f_rights[j])))
                    523:                rt |= (1 << j);
1.16      rees      524:        }
1.9       rees      525:     }
                    526:     acl[prno] = rt;
                    527:
                    528:     /* Set acl */
                    529:     sectok_apdu(fd, cla, 0xfc, 0, 0, 8, acl, 0, NULL, &sw);
                    530:     if (!sectok_swOK(sw)) {
                    531:        printf("ChangeFileACL: %s\n", sectok_get_sw(sw));
                    532:        return -1;
1.1       rees      533:     }
1.9       rees      534:
                    535:     print_acl(isdir, acl);
                    536:
1.1       rees      537:     return 0;
                    538: }
                    539:
1.3       rees      540: int jcreate(int ac, char *av[])
                    541: {
                    542:     unsigned char fid[2];
                    543:     int sw, fsize;
                    544:
                    545:     if (ac != 3) {
                    546:        printf("usage: create fid size\n");
                    547:        return -1;
                    548:     }
                    549:
                    550:     sectok_parse_fname(av[1], fid);
                    551:     sscanf(av[2], "%d", &fsize);
                    552:
1.7       rees      553:     if (fd < 0 && reset(0, NULL) < 0)
                    554:        return -1;
1.4       rees      555:     if (!aut0_vfyd)
                    556:        jaut(0, NULL);
1.3       rees      557:
                    558:     if (cyberflex_create_file(fd, cla, fid, fsize, 3, &sw) < 0) {
                    559:        printf("create_file: %s\n", sectok_get_sw(sw));
                    560:        return -1;
                    561:     }
                    562:
                    563:     return 0;
                    564: }
                    565:
                    566: int jdelete(int ac, char *av[])
                    567: {
                    568:     unsigned char fid[2];
                    569:     int sw;
                    570:
                    571:     if (ac != 2) {
                    572:        printf("usage: delete fid\n");
                    573:        return -1;
                    574:     }
                    575:
                    576:     sectok_parse_fname(av[1], fid);
                    577:
1.7       rees      578:     if (fd < 0 && reset(0, NULL) < 0)
                    579:        return -1;
1.4       rees      580:     if (!aut0_vfyd)
                    581:        jaut(0, NULL);
1.3       rees      582:
                    583:     if (cyberflex_delete_file(fd, cla, fid, &sw) < 0) {
                    584:        printf("delete_file: %s\n", sectok_get_sw(sw));
                    585:        return -1;
                    586:     }
                    587:
                    588:     return 0;
                    589: }
                    590:
1.1       rees      591: #define MAX_BUF_SIZE 256
                    592: #define MAX_APP_SIZE 4096
                    593: #define MAX_APDU_SIZE 0xfa
                    594: #define BLOCK_SIZE 8
                    595: #define MAXTOKENS 16
                    596:
1.13      rees      597: unsigned char progID[2], contID[2];
1.1       rees      598:
1.18      rees      599: #ifndef __palmos__
1.10      rees      600: int jload(int ac, char *av[])
                    601: {
1.13      rees      602:     char *cp, *filename, progname[5], contname[5];
                    603:     unsigned char aid[16], app_data[MAX_APP_SIZE], data[MAX_BUF_SIZE];
                    604:     int i, j, vflag = 0, gotprog = 0, gotcont = 0, fd_app, size, aidlen = 0, sw;
                    605:     int cont_size = 1152, inst_size = 1024;
1.10      rees      606:     des_cblock tmp;
                    607:     des_key_schedule schedule;
1.16      rees      608:     static unsigned char acl[] = {0x81, 0, 0, 0xff, 0, 0, 0, 0};
1.1       rees      609:
                    610:     optind = optreset = 1;
                    611:
1.10      rees      612:     while ((i = getopt(ac, av, "p:c:s:i:a:v")) != -1) {
                    613:        switch (i) {
1.1       rees      614:        case 'p':
1.11      rees      615:            sectok_parse_input(optarg, progID, 2);
1.13      rees      616:            gotprog = 1;
1.1       rees      617:            break;
                    618:        case 'c':
1.11      rees      619:            sectok_parse_input(optarg, contID, 2);
1.13      rees      620:            gotcont = 1;
1.1       rees      621:            break;
                    622:        case 's':
                    623:            sscanf(optarg, "%d", &cont_size);
                    624:            break;
                    625:        case 'i':
                    626:            sscanf(optarg, "%d", &inst_size);
                    627:            break;
                    628:        case 'a':
1.13      rees      629:            aidlen = sectok_parse_input(optarg, aid, sizeof aid);
1.10      rees      630:            break;
                    631:        case 'v':
                    632:            vflag = 1;
1.1       rees      633:            break;
                    634:        default:
                    635:            printf ("unknown option.  command aborted.\n");
                    636:            return -1;
                    637:        }
                    638:     }
                    639:
1.10      rees      640:     if (ac - optind < 1) {
                    641:        printf("missing file name\n");
1.1       rees      642:        return -1;
1.10      rees      643:     }
1.13      rees      644:     filename = av[optind++];
                    645:
                    646:     /*
                    647:      * We prepend 0xfc to the aid to make it a "proprietary aid".
                    648:      * See 7816-5 sec 5.2.4.
                    649:      */
                    650:     if (aidlen <= 0) {
                    651:        /* No aid given, derive from file name */
                    652:        cp = strrchr(filename, '/');
                    653:        if (cp)
                    654:            cp++;
                    655:        else
                    656:            cp = filename;
                    657:        aid[0] = 0xfc;
                    658:        strncpy(&aid[1], cp, sizeof aid - 1);
                    659:        aidlen = (aid[15] == '\0') ? strlen(aid) : 16;
                    660:     } else if (aid[0] == '#')
                    661:        aid[0] = 0xfc;
                    662:
                    663:     if (!gotprog) {
                    664:        /* No progID given, derive from aid */
                    665:        progID[0] = aid[1];
                    666:        progID[1] = 'p';
                    667:     }
                    668:
                    669:     if (!gotcont) {
                    670:        /* No contID given, derive from aid */
                    671:        contID[0] = aid[1];
                    672:        contID[1] = 'c';
                    673:     }
1.1       rees      674:
1.7       rees      675:     if (fd < 0 && reset(0, NULL) < 0)
                    676:        return -1;
1.4       rees      677:     if (!aut0_vfyd)
                    678:        jaut(0, NULL);
1.1       rees      679:
1.15      rees      680:     sectok_fmt_fid(progname, progID);
                    681:     sectok_fmt_fid(contname, contID);
1.1       rees      682:
1.10      rees      683:     if (vflag) {
1.13      rees      684:        printf ("applet file             \"%s\"\n", filename);
1.10      rees      685:        printf ("program ID              %s\n", progname);
                    686:        printf ("container ID            %s\n", contname);
                    687:        printf ("instance container size %d\n", cont_size);
                    688:        printf ("instance data size      %d\n", inst_size);
                    689:        printf ("AID                     ");
1.13      rees      690:        for (i = 0 ; i < aidlen ; i ++ )
                    691:            printf ("%02x ", aid[i]);
1.10      rees      692:        printf ("\n");
                    693:     }
1.1       rees      694:
                    695:     /* open the input file */
1.13      rees      696:     fd_app = open (filename, O_RDONLY, NULL);
1.1       rees      697:     if (fd_app == -1) {
1.13      rees      698:        fprintf (stderr, "cannot open file \"%s\"\n", filename);
1.1       rees      699:        return -1;
                    700:     }
                    701:
                    702:     /* read the input file */
                    703:     size = read (fd_app, app_data, MAX_APP_SIZE);
1.13      rees      704:     if (size <= 0) {
                    705:        fprintf (stderr, "error reading file %s\n", filename);
1.1       rees      706:        return -1;
                    707:     }
                    708:
                    709:     /* size must be able to be divided by BLOCK_SIZE */
                    710:     if (size % BLOCK_SIZE != 0) {
1.13      rees      711:        fprintf (stderr, "file \"%s\" size %d not divisible by %d\n", filename, size, BLOCK_SIZE);
1.1       rees      712:        return -1;
                    713:     }
                    714:
                    715:     /* compute the signature of the applet */
                    716:     /* initialize the result buffer */
1.10      rees      717:     memset(tmp, 0, BLOCK_SIZE);
1.1       rees      718:
                    719:     /* chain.  DES encrypt one block, XOR the cyphertext with the next block,
                    720:        ... continues until the end of the buffer */
                    721:
                    722:     des_set_key (&app_key, schedule);
                    723:
                    724:     for (i = 0; i < size/BLOCK_SIZE; i++) {
1.10      rees      725:        for (j = 0; j < BLOCK_SIZE; j++)
1.1       rees      726:            tmp[j] = tmp[j] ^ app_data[i*BLOCK_SIZE + j];
                    727:        des_ecb_encrypt (&tmp, &tmp, schedule, DES_ENCRYPT);
                    728:     }
                    729:
1.10      rees      730:     if (vflag) {
                    731:        /* print out the signature */
                    732:        printf ("signature ");
                    733:        for (j = 0; j < BLOCK_SIZE; j++ )
1.13      rees      734:            printf ("%02x ", tmp[j]);
1.10      rees      735:        printf ("\n");
1.1       rees      736:     }
                    737:
                    738:     /* select the default loader */
1.9       rees      739:     sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
1.4       rees      740:     if (!sectok_swOK(sw)) {
1.1       rees      741:        /* error */
1.4       rees      742:        printf("can't select default loader: %s\n", sectok_get_sw(sw));
1.1       rees      743:        return -1;
                    744:     }
                    745:
                    746:     /* select 3f.00 (root) */
1.3       rees      747:     if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2       rees      748:        return -1;
1.1       rees      749:
                    750:     /* create program file */
1.15      rees      751:     if (cyberflex_create_file_acl(fd, cla, progID, size, 3, acl, &sw) < 0) {
1.1       rees      752:        /* error */
1.3       rees      753:        printf("can't create %s: %s\n", progname, sectok_get_sw(sw));
1.1       rees      754:        return -1;
                    755:     }
                    756:
                    757:     /* update binary */
                    758:     for (i = 0; i < size; i += MAX_APDU_SIZE) {
                    759:        int send_size;
                    760:
                    761:        /* compute the size to be sent */
                    762:        if (size - i > MAX_APDU_SIZE) send_size = MAX_APDU_SIZE;
                    763:        else send_size = size - i;
                    764:
1.9       rees      765:        sectok_apdu(fd, cla, 0xd6, i / 256, i % 256, send_size, app_data + i, 0, NULL, &sw);
1.1       rees      766:
1.4       rees      767:        if (!sectok_swOK(sw)) {
1.1       rees      768:            /* error */
1.4       rees      769:            printf("updating binary %s: %s\n", progname, sectok_get_sw(sw));
1.1       rees      770:            return -1;
                    771:        }
                    772:     }
                    773:
                    774:     /* manage program .. validate */
1.9       rees      775:     sectok_apdu(fd, cla, 0x0a, 01, 0, 0x08, tmp, 0, NULL, &sw);
1.1       rees      776:
1.4       rees      777:     if (!sectok_swOK(sw)) {
1.1       rees      778:        /* error */
1.4       rees      779:        printf("validating applet in %s: %s\n", progname, sectok_get_sw(sw));
1.1       rees      780:        return -1;
                    781:     }
                    782:
                    783:     /* select the default loader */
1.9       rees      784:     sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
1.4       rees      785:     if (!sectok_swOK(sw)) {
1.1       rees      786:        /* error */
1.4       rees      787:        printf("selecting default loader: %s\n", sectok_get_sw(sw));
1.1       rees      788:        return -1;
                    789:     }
                    790:
                    791:     /* execute method -- call the install() method in the cardlet.
1.13      rees      792:        cardlet type 01 (applet, not application) */
1.1       rees      793:
                    794:     data[0] = 0x01;            /* cardlet type = 1 (applet, not application) */
                    795:     data[1] = progID[0];       /* FID, upper */
                    796:     data[2] = progID[1];       /* FID, lower */
1.13      rees      797:     data[3] = cont_size >> 8;  /* instance container size 0x0800 (1152) byte, upper */
                    798:     data[4] = cont_size & 0xff;        /* instance container size 0x0800 (1152) byte, lower */
1.1       rees      799:     data[5] = contID[0];       /* container ID (7778), upper */
                    800:     data[6] = contID[1];       /* container ID (7778), lower */
1.13      rees      801:     data[7] = inst_size >> 8;  /* instance size 0x0400 (1024) byte, upper */
                    802:     data[8] = inst_size & 0xff;        /* instance size 0x0400 (1024) byte, lower */
1.1       rees      803:     data[9] = 0x00;            /* AID length 0x0005, upper */
1.13      rees      804:     data[10] = aidlen;         /* AID length 0x0005, lower */
1.18      rees      805:     memcpy(&data[11], aid, aidlen);
1.1       rees      806:
1.13      rees      807:     sectok_apdu(fd, cla, 0x0c, 0x13, 0, 11 + aidlen, data, 0, NULL, &sw);
1.4       rees      808:     if (!sectok_swOK(sw)) {
1.1       rees      809:        /* error */
1.4       rees      810:        printf("executing install() method in applet %s: %s\n", progname, sectok_get_sw(sw));
1.1       rees      811:        return -1;
                    812:     }
                    813:
                    814:     /* That's it! :) */
                    815:     return 0;
                    816: }
1.18      rees      817: #endif
1.1       rees      818:
                    819: int junload(int ac, char *av[])
                    820: {
                    821:     char progname[5], contname[5];
1.20      rees      822:     int i, vflag = 0, gotprog = 0, gotcont = 0, sw;
1.10      rees      823:
                    824:     optind = optreset = 1;
1.1       rees      825:
1.10      rees      826:     while ((i = getopt(ac, av, "p:c:v")) != -1) {
                    827:        switch (i) {
                    828:        case 'p':
1.11      rees      829:            sectok_parse_input(optarg, progID, 2);
1.20      rees      830:            gotprog = 1;
1.10      rees      831:            break;
                    832:        case 'c':
1.11      rees      833:            sectok_parse_input(optarg, contID, 2);
1.20      rees      834:            gotcont = 1;
1.10      rees      835:            break;
                    836:        case 'v':
                    837:            vflag = 1;
                    838:            break;
                    839:        default:
                    840:            printf ("unknown option.  command aborted.\n");
                    841:            return -1;
                    842:        }
                    843:     }
1.20      rees      844:
                    845:     if (ac - optind >= 1) {
                    846:        /* Derive progID and contID from filename */
                    847:        if (!gotprog) {
                    848:            progID[0] = av[optind][0];
                    849:            progID[1] = 'p';
                    850:            gotprog = 1;
                    851:        }
                    852:        if (!gotcont) {
                    853:            contID[0] = av[optind][0];
                    854:            contID[1] = 'c';
                    855:            gotcont = 1;
                    856:        }
                    857:     }
                    858:
                    859:     /* Use old defaults */
                    860:     if (!gotprog)
                    861:        memcpy(progID, "ww", 2);
                    862:     if (!gotcont)
                    863:        memcpy(contID, "wx", 2);
1.1       rees      864:
1.7       rees      865:     if (fd < 0 && reset(0, NULL) < 0)
                    866:        return -1;
1.4       rees      867:     if (!aut0_vfyd)
                    868:        jaut(0, NULL);
1.1       rees      869:
1.15      rees      870:     sectok_fmt_fid(progname, progID);
                    871:     sectok_fmt_fid(contname, contID);
1.1       rees      872:
1.10      rees      873:     if (vflag) {
                    874:        printf ("program ID              %s\n", progname);
                    875:        printf ("container ID            %s\n", contname);
                    876:     }
1.1       rees      877:
                    878:     /* select 3f.00 (root) */
1.3       rees      879:     if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
                    880:        printf("can't select root: %s\n", sectok_get_sw(sw));
1.2       rees      881:        return -1;
1.3       rees      882:     }
1.1       rees      883:
                    884:     /* select program file */
1.3       rees      885:     if (sectok_selectfile(fd, cla, progID, &sw) >= 0) {
1.1       rees      886:
1.2       rees      887:        /* manage program -- reset */
1.9       rees      888:        sectok_apdu(fd, cla, 0x0a, 02, 0, 0, NULL, 0, NULL, &sw);
1.4       rees      889:        if (!sectok_swOK(sw)) {
1.2       rees      890:            /* error */
1.4       rees      891:            printf("resetting applet: %s\n", sectok_get_sw(sw));
1.2       rees      892:        }
1.1       rees      893:
1.2       rees      894:        /* delete program file */
1.3       rees      895:        if (cyberflex_delete_file(fd, cla, progID, &sw) < 0)
                    896:            printf("delete_file %s: %s\n", progname, sectok_get_sw(sw));
1.10      rees      897:     } else if (vflag)
1.2       rees      898:        printf ("no program file... proceed to delete data container\n");
1.1       rees      899:
                    900:     /* delete data container */
1.3       rees      901:     if (cyberflex_delete_file(fd, cla, contID, &sw) < 0)
                    902:        printf("delete_file %s: %s\n", contname, sectok_get_sw(sw));
1.1       rees      903:
                    904:     return 0;
                    905: }
                    906:
1.18      rees      907: #ifndef __palmos__
1.1       rees      908: #define DELIMITER " :\t\n"
                    909: #define KEY_BLOCK_SIZE 14
                    910:
                    911: /* download DES keys into 3f.00/00.11 */
                    912: int cyberflex_load_key (int fd, unsigned char *buf)
                    913: {
1.9       rees      914:     int sw, argc = 0, i, j, tmp;
1.1       rees      915:     unsigned char *token;
                    916:     unsigned char data[MAX_BUF_SIZE];
                    917:     unsigned char key[BLOCK_SIZE];
                    918:
                    919: #if 0
                    920:     /* select the default loader */
                    921:     rv = scwrite(fd, cla, 0xa4, 0x04, 0, 0x00, NULL, &r1, &r2);
                    922:     if (r1 != 0x90 && r1 != 0x61) {
                    923:        // error
                    924:            printf ("selecting the default loader: ");
                    925:        print_r1r2 (r1, r2);
                    926:        return -1;
                    927:     }
                    928: #endif
                    929:
                    930:     printf ("ca_load_key buf=%s\n", buf);
                    931:     token = strtok (buf, DELIMITER);
                    932:     token = strtok (NULL, DELIMITER);
                    933:     if (token == NULL) {
                    934:        printf ("Usage: jk number_of_keys\n");
                    935:        return -1;
                    936:     }
                    937:     argc = atoi (token);
                    938:
                    939:     if (argc > 2) {
                    940:        printf ("current Cyberflex Access cannot download more than 2 keys to the key file.  Sorry. :(\n");
                    941:        return -1;
                    942:     }
                    943:
                    944:     if (argc < 0) {
                    945:        printf ("you want to down load %d keys??\n", argc);
                    946:        return -1;
                    947:     }
                    948:
1.4       rees      949:     if (!aut0_vfyd)
                    950:        jaut(0, NULL);
                    951:
1.1       rees      952:     /* Now let's do it. :) */
                    953:
                    954:     /* add the AUT0 */
1.7       rees      955:     cyberflex_fill_key_block (data, 0, 1, AUT0);
1.1       rees      956:
                    957:     /* add the applet sign key */
                    958:     cyberflex_fill_key_block (data+KEY_BLOCK_SIZE, 5, 0, app_key);
                    959:
                    960:     /* then add user defined keys */
                    961:     for ( i = 0 ; i < argc ; i++ ) {
                    962:        printf ("key %d : ", i);
                    963:        for ( j = 0 ; j < BLOCK_SIZE ; j++ ) {
                    964:            fscanf (cmdf, "%02x", &tmp);
                    965:            key[j] = (unsigned char)tmp;
                    966:        }
                    967:
                    968:        cyberflex_fill_key_block (data + 28 + i*KEY_BLOCK_SIZE, 6 + i, 0, key);
                    969:     }
                    970:
                    971:     /* add the suffix */
                    972:     data[28 + argc*KEY_BLOCK_SIZE] = 0;
                    973:     data[28 + argc*KEY_BLOCK_SIZE + 1] = 0;
                    974:
                    975:     for ( i = 0 ; i < KEY_BLOCK_SIZE * (argc + 2) + 2; i++ )
                    976:        printf ("%02x ", data[i]);
                    977:     printf ("\n");
                    978:
                    979:     /* select 3f.00 (root) */
1.3       rees      980:     if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
                    981:        printf("select root: %s\n", sectok_get_sw(sw));
1.2       rees      982:        return -1;
1.3       rees      983:     }
1.1       rees      984:
                    985:     /* select 00.11 (key file) */
1.3       rees      986:     if (sectok_selectfile(fd, cla, key_fid, &sw) < 0) {
                    987:        printf("select key file: %s\n", sectok_get_sw(sw));
1.2       rees      988:        return -1;
1.3       rees      989:     }
1.1       rees      990:
                    991:     /* all righty, now let's send it to the card! :) */
1.9       rees      992:     sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE * (argc + 2) + 2, data, 0, NULL, &sw);
1.4       rees      993:     if (!sectok_swOK(sw)) {
1.1       rees      994:        /* error */
1.4       rees      995:        printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1       rees      996:        return -1;
                    997:     }
                    998:
                    999:     return 0;
                   1000: }
                   1001:
                   1002: /* download AUT0 key into 3f.00/00.11 */
1.5       rees     1003: int jsetpass(int ac, char *av[])
1.1       rees     1004: {
1.9       rees     1005:     int sw;
1.1       rees     1006:     unsigned char data[MAX_BUF_SIZE];
1.5       rees     1007:     unsigned char AUT0[20];
1.1       rees     1008:
1.5       rees     1009:     if (!aut0_vfyd && jaut(0, NULL) < 0)
                   1010:        return -1;
1.1       rees     1011:
1.14      rees     1012:     if (get_AUT0(ac, av, "Enter new AUT0 passphrase: ", 1, AUT0) < 0)
1.5       rees     1013:        return -1;
1.1       rees     1014:
1.5       rees     1015:     cyberflex_fill_key_block (data, 0, 1, AUT0);
1.1       rees     1016:
                   1017: #if 0
                   1018:     /* add the suffix */
                   1019:     data[KEY_BLOCK_SIZE] = 0;
                   1020:     data[KEY_BLOCK_SIZE + 1] = 0;
                   1021: #endif
                   1022:
1.5       rees     1023: #ifdef DEBUG
                   1024:     for (i = 0; i < KEY_BLOCK_SIZE; i++)
1.1       rees     1025:        printf ("%02x ", data[i]);
                   1026:     printf ("\n");
1.5       rees     1027: #endif
1.1       rees     1028:
                   1029:     /* select 3f.00 (root) */
1.3       rees     1030:     if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2       rees     1031:        return -1;
1.1       rees     1032:
                   1033:     /* select 00.11 (key file) */
1.3       rees     1034:     if (sectok_selectfile(fd, cla, key_fid, &sw) < 0)
1.2       rees     1035:        return -1;
1.1       rees     1036:
                   1037:     /* all righty, now let's send it to the card! :) */
1.9       rees     1038:     sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE, data, 0, NULL, &sw);
1.4       rees     1039:     if (!sectok_swOK(sw)) {
1.1       rees     1040:        /* error */
1.4       rees     1041:        printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1       rees     1042:        return -1;
                   1043:     }
                   1044:
                   1045:     return 0;
                   1046: }
                   1047:
                   1048: /* download RSA private key into 3f.00/00.12 */
                   1049: int cyberflex_load_rsa(int fd, unsigned char *buf)
                   1050: {
1.9       rees     1051:     int sw, i, j, tmp;
1.1       rees     1052:     static unsigned char key_fid[] = {0x00, 0x12};
                   1053:     static char *key_names[NUM_RSA_KEY_ELEMENTS]= {"p", "q", "1/p mod q",
                   1054:                                                       "d mod (p-1)", "d mod (q-1)"};
                   1055:     unsigned char *key_elements[NUM_RSA_KEY_ELEMENTS];
                   1056:
                   1057:     printf ("ca_load_rsa_priv buf=%s\n", buf);
                   1058:
                   1059:     printf ("input 1024 bit RSA CRT key\n");
                   1060:     for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) {
                   1061:        printf ("%s (%d bit == %d byte) : ", key_names[i],
                   1062:                RSA_BIT_LEN/2, RSA_BIT_LEN/2/8);
                   1063:        key_elements[i] = (unsigned char *) malloc(RSA_BIT_LEN/8);
                   1064:        for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
                   1065:            fscanf (cmdf, "%02x", &tmp);
                   1066:            key_elements[i][j] = (unsigned char)tmp;
                   1067:        }
                   1068:     }
                   1069:
                   1070: #ifdef DEBUG
                   1071:     printf ("print RSA CRT key\n");
                   1072:     for (i = 0 ; i < NUM_RSA_KEY_ELEMENTS ; i ++ ) {
                   1073:        printf ("%s : ", key_names[i]);
                   1074:        for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
                   1075:            printf ("%02x ", key_elements[i][j]);
                   1076:        }
                   1077:     }
                   1078: #endif
1.4       rees     1079:
                   1080:     if (!aut0_vfyd)
                   1081:        jaut(0, NULL);
1.1       rees     1082:
1.9       rees     1083:     cyberflex_load_rsa_priv(fd, cla, key_fid, NUM_RSA_KEY_ELEMENTS, RSA_BIT_LEN,
1.3       rees     1084:                                 key_elements, &sw);
1.2       rees     1085:
1.9       rees     1086:     if (!sectok_swOK(sw))
1.3       rees     1087:        printf("load_rsa_priv: %s\n", sectok_get_sw(sw));
1.1       rees     1088:
                   1089:     for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
                   1090:        free(key_elements[i]);
1.9       rees     1091:     return 0;
1.1       rees     1092: }
1.18      rees     1093: #endif