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

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