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