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