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

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