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