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