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

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