[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.9

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