Annotation of src/usr.bin/sectok/cyberflex.c, Revision 1.23
1.23 ! deraadt 1: /* $OpenBSD: cyberflex.c,v 1.22 2002/03/20 22:30:58 rees 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 */
! 421: sectok_fmt_fid(fname, &buf[4]);
! 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:
! 682: sectok_fmt_fid(progname, progID);
! 683: sectok_fmt_fid(contname, contID);
! 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.23 ! deraadt 872: sectok_fmt_fid(progname, progID);
! 873: sectok_fmt_fid(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