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