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