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