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