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