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