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

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