Annotation of src/usr.bin/sectok/cyberflex.c, Revision 1.6
1.6 ! rees 1: /* $Id: cyberflex.c,v 1.5 2001/07/16 23:09:36 rees Exp $ */
1.1 rees 2:
3: /*
4: copyright 1999, 2000
5: the regents of the university of michigan
6: all rights reserved
7:
8: permission is granted to use, copy, create derivative works
9: and redistribute this software and such derivative works
10: for any purpose, so long as the name of the university of
11: michigan is not used in any advertising or publicity
12: pertaining to the use or distribution of this software
13: without specific, written prior authorization. if the
14: above copyright notice or any other identification of the
15: university of michigan is included in any copy of any
16: portion of this software, then the disclaimer below must
17: also be included.
18:
19: this software is provided as is, without representation
20: from the university of michigan as to its fitness for any
21: purpose, and without warranty by the university of
22: michigan of any kind, either express or implied, including
23: without limitation the implied warranties of
24: merchantability and fitness for a particular purpose. the
25: regents of the university of michigan shall not be liable
26: for any damages, including special, indirect, incidental, or
27: consequential damages, with respect to any claim arising
28: out of or in connection with the use of the software, even
29: if it has been or is hereafter advised of the possibility of
30: such damages.
31: */
32:
1.5 rees 33: #include <sys/types.h>
1.1 rees 34: #include <unistd.h>
35: #include <stdlib.h>
36: #include <stdio.h>
37: #include <signal.h>
38: #include <string.h>
39: #include <fcntl.h>
40: #ifdef __linux
41: #include <openssl/des.h>
42: #else /* __linux */
43: #include <des.h>
44: #endif
1.5 rees 45: #include <sha1.h>
1.1 rees 46: #include <sectok.h>
1.3 rees 47: #include <sc7816.h>
1.1 rees 48:
49: #include "sc.h"
50:
51: #ifdef __sun
52: #define des_set_key(key, schedule) des_key_sched(key, schedule)
53: #endif
54:
55: #define MAX_KEY_FILE_SIZE 1024
56: #define NUM_RSA_KEY_ELEMENTS 5
57: #define RSA_BIT_LEN 1024
58: #define KEY_FILE_HEADER_SIZE 8
59:
60: static unsigned char key_fid[] = {0x00, 0x11};
61: static unsigned char DFLTATR[] = {0x81, 0x10, 0x06, 0x01};
1.5 rees 62: static unsigned char DFLTAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
1.1 rees 63:
1.4 rees 64: int aut0_vfyd;
65:
1.1 rees 66: /* default signed applet key of Cyberflex Access */
67: static des_cblock app_key = {0x6A, 0x21, 0x36, 0xF5, 0xD8, 0x0C, 0x47, 0x83};
68:
69: char *apptype[] = {
70: "?",
71: "applet",
72: "app",
73: "app/applet",
74: };
75:
76: char *appstat[] = {
77: "?",
78: "created",
79: "installed",
80: "registered",
81: };
82:
83: char *filestruct[] = {
84: "binary",
85: "fixed rec",
86: "variable rec",
87: "cyclic",
88: "program",
89: };
90:
1.5 rees 91: static int
92: get_AUT0(int ac, char *av[], char *prompt, unsigned char *digest)
93: {
94: int i, dflag = 0, xflag = 0;
95: SHA1_CTX ctx;
96: char *s;
97:
98: optind = optreset = 1;
99: opterr = 0;
100:
101: while ((i = getopt(ac, av, "dx:")) != -1) {
102: switch (i) {
103: case 'd':
104: memmove(digest, DFLTAUT0, sizeof DFLTAUT0);
105: dflag = 1;
106: break;
107: case 'x':
108: if (parse_input(optarg, digest, 8) != 8) {
109: printf("AUT0 must be length 8\n");
110: return -1;
111: }
112: xflag = 1;
113: break;
114: }
115: }
116:
117: if (!dflag && !xflag) {
118: SHA1Init(&ctx);
119: s = getpass(prompt);
120: SHA1Update(&ctx, s, strlen(s));
121: bzero(s, strlen(s));
122: SHA1Final(digest, &ctx);
123: }
124:
125: return 0;
126: }
127:
1.6 ! rees 128: int jlogin(int ac, char *av[])
1.4 rees 129: {
1.5 rees 130: int i, vflag = 0, sw;
131: unsigned char AUT0[20];
1.4 rees 132:
133: if (fd < 0)
1.5 rees 134: reset(0, NULL);
135:
136: optind = optreset = 1;
1.4 rees 137:
1.5 rees 138: while ((i = getopt(ac, av, "dvx:")) != -1) {
1.4 rees 139: switch (i) {
140: case 'v':
141: vflag = 1;
142: break;
143: }
144: }
145:
1.5 rees 146: if (get_AUT0(ac, av, "Enter AUT0 passphrase: ", AUT0) < 0)
147: return -1;
148:
1.4 rees 149: cla = cyberflex_inq_class(fd);
1.5 rees 150:
151: if (vflag) {
1.4 rees 152: printf("Class %02x\n", cla);
1.5 rees 153: for (i = 0; i < 8; i++)
154: printf("%02x ", AUT0[i]);
155: printf("\n");
156: }
157:
158: sectok_apdu(fd, cla, 0x2a, 0, 0, 8, AUT0, 0, NULL, &sw);
1.4 rees 159:
1.5 rees 160: if (!sectok_swOK(sw)) {
161: printf("AUT0 failed: %s\n", sectok_get_sw(sw));
162: aut0_vfyd = 0;
163: return -1;
164: }
165: aut0_vfyd = 1;
166: return 0;
1.6 ! rees 167: }
! 168:
! 169: int jaut(int ac, char *av[])
! 170: {
! 171: static char *jlav[] = {"login", "-d", NULL};
! 172:
! 173: return jlogin(2, jlav);
1.4 rees 174: }
175:
1.1 rees 176: int jdefault(int ac, char *av[])
177: {
178: unsigned char buf[8];
1.4 rees 179: int i, p1 = 4, sw;
1.1 rees 180:
181: optind = optreset = 1;
182:
183: while ((i = getopt(ac, av, "d")) != -1) {
184: switch (i) {
185: case 'd':
186: p1 = 5;
187: break;
188: }
189: }
190:
191: if (fd < 0)
192: reset(0, NULL);
1.4 rees 193: if (!aut0_vfyd)
194: jaut(0, NULL);
1.1 rees 195:
1.4 rees 196: sectok_apdu(fd, cla, 0x08, p1, 0, 0, buf, 0, NULL, &sw);
197: if (!sectok_swOK(sw)) {
1.1 rees 198: /* error */
1.4 rees 199: sectok_print_sw(sw);
1.1 rees 200: return -1;
201: }
202: return 0;
203: }
204:
205: int jatr(int ac, char *av[])
206: {
207: unsigned char buf[64];
1.4 rees 208: int n = 0, sw;
1.1 rees 209:
210: if (fd < 0)
211: reset(0, NULL);
212:
213: buf[n++] = 0x90;
214: buf[n++] = 0x94; /* TA1 */
215: buf[n++] = 0x40; /* TD1 */
216: buf[n++] = 0x28; /* TC2 (WWT=4sec) */
217: if (ac > optind) {
218: /* set historical bytes from command line */
219: n += parse_input(av[1], &buf[n], 15);
220: } else {
221: /* no historical bytes given, use default */
222: memmove(&buf[n], DFLTATR, sizeof DFLTATR);
223: n += sizeof DFLTATR;
224: }
225: buf[0] |= ((n - 2) & 0xf);
1.4 rees 226: sectok_apdu(fd, cla, 0xfa, 0, 0, n, buf, 0, NULL, &sw);
227: if (!sectok_swOK(sw)) {
1.1 rees 228: /* error */
1.4 rees 229: sectok_print_sw(sw);
1.1 rees 230: return -1;
231: }
232: return 0;
233: }
234:
235: int jdata(int ac, char *av[])
236: {
237: unsigned char buf[32];
1.4 rees 238: int i, sw;
1.1 rees 239:
240: if (fd < 0)
241: reset(0, NULL);
242:
1.4 rees 243: sectok_apdu(fd, cla, 0xca, 0, 1, 0, NULL, 0x16, buf, &sw);
244: if (sectok_swOK(sw)) {
1.1 rees 245: printf("serno ");
246: for (i = 0; i < 6; i++)
247: printf("%02x ", buf[i]);
248: printf("batch %02x sver %d.%02d ", buf[6], buf[7], buf[8]);
249: if (buf[9] == 0x0c)
250: printf("augmented ");
251: else if (buf[9] == 0x0b)
252: ;
253: else
254: printf("unknown ");
255: printf("crypto %9.9s class %02x\n", &buf[10], buf[19]);
256: } else {
257: /* error */
1.4 rees 258: sectok_print_sw(sw);
1.1 rees 259: }
260: return 0;
261: }
262:
263: #define JDIRSIZE 40
264:
265: int ls(int ac, char *av[])
266: {
1.4 rees 267: int p2, f0, f1, sw;
1.1 rees 268: char ftype[32], fname[6];
269: unsigned char buf[JDIRSIZE];
270:
271: if (fd < 0)
272: reset(0, NULL);
273:
274: for (p2 = 0; ; p2++) {
1.4 rees 275: if (sectok_apdu(fd, cla, 0xa8, 0, p2, 0, NULL, JDIRSIZE, buf, &sw) < 0)
1.1 rees 276: break;
1.4 rees 277: if (!sectok_swOK(sw))
1.1 rees 278: break;
279: f0 = buf[4];
280: f1 = buf[5];
281: if (f0 == 0xff || f0 + f1 == 0)
282: continue;
283: sectok_fmt_fid(fname, f0, f1);
284: if (buf[6] == 1)
285: /* root */
286: sprintf(ftype, "root");
287: else if (buf[6] == 2) {
288: /* DF */
289: if (buf[12] == 27)
290: sprintf(ftype, "%s %s", appstat[buf[10]], apptype[buf[9]]);
291: else
292: sprintf(ftype, "directory");
293: } else if (buf[6] == 4)
294: /* EF */
295: sprintf(ftype, "%s", filestruct[buf[13]]);
296: printf("%4s %5d %s\n", fname, (buf[2] << 8) | buf[3], ftype);
297: }
298: return 0;
299: }
300:
1.3 rees 301: int jcreate(int ac, char *av[])
302: {
303: unsigned char fid[2];
304: int sw, fsize;
305:
306: if (ac != 3) {
307: printf("usage: create fid size\n");
308: return -1;
309: }
310:
311: sectok_parse_fname(av[1], fid);
312: sscanf(av[2], "%d", &fsize);
313:
314: if (fd < 0)
315: reset(0, NULL);
1.4 rees 316: if (!aut0_vfyd)
317: jaut(0, NULL);
1.3 rees 318:
319: if (cyberflex_create_file(fd, cla, fid, fsize, 3, &sw) < 0) {
320: printf("create_file: %s\n", sectok_get_sw(sw));
321: return -1;
322: }
323:
324: return 0;
325: }
326:
327: int jdelete(int ac, char *av[])
328: {
329: unsigned char fid[2];
330: int sw;
331:
332: if (ac != 2) {
333: printf("usage: delete fid\n");
334: return -1;
335: }
336:
337: sectok_parse_fname(av[1], fid);
338:
339: if (fd < 0)
340: reset(0, NULL);
1.4 rees 341: if (!aut0_vfyd)
342: jaut(0, NULL);
1.3 rees 343:
344: if (cyberflex_delete_file(fd, cla, fid, &sw) < 0) {
345: printf("delete_file: %s\n", sectok_get_sw(sw));
346: return -1;
347: }
348:
349: return 0;
350: }
351:
1.1 rees 352: #define MAX_BUF_SIZE 256
353: #define MAX_APP_SIZE 4096
354: #define MAX_APDU_SIZE 0xfa
355: #define BLOCK_SIZE 8
356: #define MAXTOKENS 16
357:
358: unsigned char *app_name;
359: unsigned char progID[2], contID[2], aid[MAX_BUF_SIZE];
360: int cont_size, inst_size;
361: int aid_len;
362:
363: int analyze_load_options(int ac, char *av[])
364: {
365: int i, rv;
366:
367: progID[0] = 0x77;
368: progID[1] = 0x77;
369: contID[0] = 0x77;
370: contID[1] = 0x78;
371: cont_size = 1152;
372: inst_size = 1024;
373: aid_len = 5;
374:
375: for (i = 0 ; i < 16 ; i ++)
376: aid[i] = 0x77;
377:
378: /* applet file name */
379: app_name = av[ac - 1];
380:
381: optind = optreset = 1;
382:
383: /* switch on options */
384: while (1) {
385: rv = getopt (ac, av, "p:c:s:i:a:");
386: if (rv == -1) break;
387: /*printf ("rv=%c, optarg=%s\n", rv, optarg);*/
388: switch (rv) {
389: case 'p':
390: parse_input(optarg, progID, 2);
391: break;
392: case 'c':
393: parse_input(optarg, contID, 2);
394: break;
395: case 's':
396: sscanf(optarg, "%d", &cont_size);
397: break;
398: case 'i':
399: sscanf(optarg, "%d", &inst_size);
400: break;
401: case 'a':
402: aid_len = parse_input(optarg, aid, sizeof aid);
403: /*printf ("aid_len = %d\n", aid_len);*/
404: break;
405: default:
406: printf ("unknown option. command aborted.\n");
407: return -1;
408: }
409: }
410:
411: return 0;
412: }
413:
414: int jload(int ac, char *av[])
415: {
416: char progname[5], contname[5];
417: unsigned char app_data[MAX_APP_SIZE],
418: data[MAX_BUF_SIZE];
1.4 rees 419: int i, j, fd_app, size, rv, sw;
1.1 rees 420: des_cblock tmp;
421: des_key_schedule schedule;
422:
423: if (analyze_load_options(ac, av) < 0)
424: return -1;
425:
426: if (fd < 0)
427: reset(0, NULL);
1.4 rees 428: if (!aut0_vfyd)
429: jaut(0, NULL);
1.1 rees 430:
431: sectok_fmt_fid(progname, progID[0], progID[1]);
432: sectok_fmt_fid(contname, contID[0], contID[1]);
433:
434: printf ("applet file \"%s\"\n", app_name);
435: printf ("program ID %s\n", progname);
436: printf ("container ID %s\n", contname);
437: printf ("instance container size %d\n", cont_size);
438: printf ("instance data size %d\n", inst_size);
439: printf ("AID ");
440: for (i = 0 ; i < aid_len ; i ++ )
441: printf ("%02x", (unsigned char)aid[i]);
442: printf ("\n");
443:
444: /* open the input file */
445: fd_app = open (app_name, O_RDONLY, NULL);
446: if (fd_app == -1) {
447: fprintf (stderr, "cannot open file \"%s\"\n", app_name);
448: return -1;
449: }
450:
451: /* read the input file */
452: size = read (fd_app, app_data, MAX_APP_SIZE);
453: if (size == 0) {
454: fprintf (stderr, "file %s size 0??\n", app_name);
455: return -1;
456: }
457: if (size == -1) {
458: fprintf (stderr, "error reading file %s\n", app_name);
459: return -1;
460: }
461:
462: /*printf ("file size %d\n", size);*/
463:
464: /* size must be able to be divided by BLOCK_SIZE */
465: if (size % BLOCK_SIZE != 0) {
466: fprintf (stderr, "file (%s) size cannot be divided by BLOCK_SIZE.\n",
467: app_name);
468: return -1;
469: }
470:
471: /* compute the signature of the applet */
472: /* initialize the result buffer */
473: for (j = 0; j < BLOCK_SIZE; j++ ) {
474: tmp[j] = 0;
475: }
476:
477: /* chain. DES encrypt one block, XOR the cyphertext with the next block,
478: ... continues until the end of the buffer */
479:
480: des_set_key (&app_key, schedule);
481:
482: for (i = 0; i < size/BLOCK_SIZE; i++) {
483: for (j = 0; j < BLOCK_SIZE; j++ ){
484: tmp[j] = tmp[j] ^ app_data[i*BLOCK_SIZE + j];
485: }
486: des_ecb_encrypt (&tmp, &tmp, schedule, DES_ENCRYPT);
487: }
488:
489: /* print out the signature */
490: printf ("signature ");
491: for (j = 0; j < BLOCK_SIZE; j++ ) {
492: printf ("%02x", tmp[j]);
493: }
494: printf ("\n");
495:
496: /* select the default loader */
1.4 rees 497: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
498: if (!sectok_swOK(sw)) {
1.1 rees 499: /* error */
1.4 rees 500: printf("can't select default loader: %s\n", sectok_get_sw(sw));
1.1 rees 501: return -1;
502: }
503:
504: /* select 3f.00 (root) */
1.3 rees 505: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2 rees 506: return -1;
1.1 rees 507:
508: /* create program file */
1.3 rees 509: if (cyberflex_create_file(fd, cla, progID, size, 3, &sw) < 0) {
1.1 rees 510: /* error */
1.3 rees 511: printf("can't create %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 512: return -1;
513: }
514:
515: /* update binary */
516: for (i = 0; i < size; i += MAX_APDU_SIZE) {
517: int send_size;
518:
519: /* compute the size to be sent */
520: if (size - i > MAX_APDU_SIZE) send_size = MAX_APDU_SIZE;
521: else send_size = size - i;
522:
1.4 rees 523: rv = sectok_apdu(fd, cla, 0xd6, i / 256, i % 256, send_size, app_data + i, 0, NULL, &sw);
1.1 rees 524:
1.4 rees 525: if (!sectok_swOK(sw)) {
1.1 rees 526: /* error */
1.4 rees 527: printf("updating binary %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 528: return -1;
529: }
530: }
531:
532: /* manage program .. validate */
1.4 rees 533: rv = sectok_apdu(fd, cla, 0x0a, 01, 0, 0x08, tmp, 0, NULL, &sw);
1.1 rees 534:
1.4 rees 535: if (!sectok_swOK(sw)) {
1.1 rees 536: /* error */
1.4 rees 537: printf("validating applet in %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 538: return -1;
539: }
540:
541: /* select the default loader */
1.4 rees 542: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
543: if (!sectok_swOK(sw)) {
1.1 rees 544: /* error */
1.4 rees 545: printf("selecting default loader: %s\n", sectok_get_sw(sw));
1.1 rees 546: return -1;
547: }
548:
549: /* execute method -- call the install() method in the cardlet.
550: cardlet type 01 (applet, not application)
551: program ID (7777)
552: instance container size (0800 (1152))
553: instance container ID (7778)
554: instance data size (0400 (1024))
555: AID length (0005 (5 byte))
556: AID (7777777777) */
557:
558: data[0] = 0x01; /* cardlet type = 1 (applet, not application) */
559: data[1] = progID[0]; /* FID, upper */
560: data[2] = progID[1]; /* FID, lower */
561: data[3] = cont_size / 256; /* instance container size 0x0800 (1152) byte, upper */
562: data[4] = cont_size % 256; /* instance container size 0x0800 (1152) byte, lower */
563: data[5] = contID[0]; /* container ID (7778), upper */
564: data[6] = contID[1]; /* container ID (7778), lower */
565: data[7] = inst_size / 256; /* instance size 0x0400 (1024) byte, upper */
566: data[8] = inst_size % 256; /* instance size 0x0400 (1024) byte, lower */
567: data[9] = 0x00; /* AID length 0x0005, upper */
568: data[10] = aid_len; /* AID length 0x0005, lower */
569: for (i = 0; i < aid_len; i++) data[i + 11] = (unsigned int)aid[i];
570: /* AID (7777777777) */
571:
1.4 rees 572: rv = sectok_apdu(fd, cla, 0x0c, 0x13, 0, 11 + aid_len, data, 0, NULL, &sw);
573: if (!sectok_swOK(sw)) {
1.1 rees 574: /* error */
1.4 rees 575: printf("executing install() method in applet %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 576: return -1;
577: }
578:
579: /* That's it! :) */
580: return 0;
581: }
582:
583: int junload(int ac, char *av[])
584: {
585: char progname[5], contname[5];
1.4 rees 586: int sw, rv;
1.1 rees 587:
588: if (analyze_load_options(ac, av) < 0)
589: return -1;
590:
591: if (fd < 0)
592: reset(0, NULL);
1.4 rees 593: if (!aut0_vfyd)
594: jaut(0, NULL);
1.1 rees 595:
596: sectok_fmt_fid(progname, progID[0], progID[1]);
597: sectok_fmt_fid(contname, contID[0], contID[1]);
598:
599: printf ("program ID %s\n", progname);
600: printf ("container ID %s\n", contname);
601:
602: /* select 3f.00 (root) */
1.3 rees 603: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
604: printf("can't select root: %s\n", sectok_get_sw(sw));
1.2 rees 605: return -1;
1.3 rees 606: }
1.1 rees 607:
608: /* select program file */
1.3 rees 609: if (sectok_selectfile(fd, cla, progID, &sw) >= 0) {
1.1 rees 610:
1.2 rees 611: /* manage program -- reset */
1.4 rees 612: rv = sectok_apdu(fd, cla, 0x0a, 02, 0, 0, NULL, 0, NULL, &sw);
613: if (!sectok_swOK(sw)) {
1.2 rees 614: /* error */
1.4 rees 615: printf("resetting applet: %s\n", sectok_get_sw(sw));
1.2 rees 616: }
1.1 rees 617:
1.2 rees 618: /* delete program file */
1.3 rees 619: if (cyberflex_delete_file(fd, cla, progID, &sw) < 0)
620: printf("delete_file %s: %s\n", progname, sectok_get_sw(sw));
1.2 rees 621: } else
622: printf ("no program file... proceed to delete data container\n");
1.1 rees 623:
624: /* delete data container */
1.3 rees 625: if (cyberflex_delete_file(fd, cla, contID, &sw) < 0)
626: printf("delete_file %s: %s\n", contname, sectok_get_sw(sw));
1.1 rees 627:
628: return 0;
629: }
630:
631: int jselect(int ac, char *av[])
632: {
1.4 rees 633: int i, sw, rv;
1.1 rees 634: unsigned char data[MAX_BUF_SIZE];
635:
636: optind = optreset = 1;
637:
638: if (analyze_load_options(ac, av) < 0)
639: return -1;
640:
641: if (fd < 0)
642: reset(0, NULL);
643:
644: printf ("select applet\n");
645: printf ("AID ");
646: for (i = 0 ; i < aid_len ; i ++ )
647: printf ("%02x", (unsigned char)aid[i]);
648: printf ("\n");
649:
650: /* select the cardlet (7777777777) */
651: for (i = 0; i < aid_len; i++) data[i] = (unsigned char)aid[i];
652: /* quick hack in select_applet()
653: even with F0 card, select applet APDU (00 a4 04)
654: only accepts class byte 00 (not f0) */
655:
1.4 rees 656: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, aid_len, data, 0, NULL, &sw);
657: if (!sectok_swOK(sw)) {
1.1 rees 658: /* error */
659: printf ("selecting the cardlet: ");
660: for (i = 0 ; i < aid_len ; i ++ ) {
661: printf ("%02x", (unsigned char)aid[i]);
662: }
663: printf ("\n");
1.4 rees 664: sectok_print_sw(sw);
1.1 rees 665: return -1;
666: }
667:
668: return 0;
669: }
670:
671: int jdeselect(int ac, char *av[])
672: {
1.3 rees 673: int sw;
1.1 rees 674:
675: if (fd < 0)
676: reset(0, NULL);
677:
1.3 rees 678: sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
679: if (!sectok_swOK(sw)) {
1.1 rees 680: /* error */
1.3 rees 681: printf("selecting default loader: %s\n", sectok_get_sw(sw));
1.1 rees 682: return -1;
683: }
684:
685: return 0;
686: }
687:
688: #define DELIMITER " :\t\n"
689: #define KEY_BLOCK_SIZE 14
690:
691: /* download DES keys into 3f.00/00.11 */
692: int cyberflex_load_key (int fd, unsigned char *buf)
693: {
1.4 rees 694: int sw, rv, argc = 0, i, j, tmp;
1.1 rees 695: unsigned char *token;
696: unsigned char data[MAX_BUF_SIZE];
697: unsigned char key[BLOCK_SIZE];
698:
699: #if 0
700: /* select the default loader */
701: rv = scwrite(fd, cla, 0xa4, 0x04, 0, 0x00, NULL, &r1, &r2);
702: if (r1 != 0x90 && r1 != 0x61) {
703: // error
704: printf ("selecting the default loader: ");
705: print_r1r2 (r1, r2);
706: return -1;
707: }
708: #endif
709:
710: printf ("ca_load_key buf=%s\n", buf);
711: token = strtok (buf, DELIMITER);
712: token = strtok (NULL, DELIMITER);
713: if (token == NULL) {
714: printf ("Usage: jk number_of_keys\n");
715: return -1;
716: }
717: argc = atoi (token);
718:
719: if (argc > 2) {
720: printf ("current Cyberflex Access cannot download more than 2 keys to the key file. Sorry. :(\n");
721: return -1;
722: }
723:
724: if (argc < 0) {
725: printf ("you want to down load %d keys??\n", argc);
726: return -1;
727: }
728:
1.4 rees 729: if (!aut0_vfyd)
730: jaut(0, NULL);
731:
1.1 rees 732: /* Now let's do it. :) */
733:
734: /* add the AUT0 */
1.5 rees 735: cyberflex_fill_key_block (data, 0, 1, DFLTAUT0);
1.1 rees 736:
737: /* add the applet sign key */
738: cyberflex_fill_key_block (data+KEY_BLOCK_SIZE, 5, 0, app_key);
739:
740: /* then add user defined keys */
741: for ( i = 0 ; i < argc ; i++ ) {
742: printf ("key %d : ", i);
743: for ( j = 0 ; j < BLOCK_SIZE ; j++ ) {
744: fscanf (cmdf, "%02x", &tmp);
745: key[j] = (unsigned char)tmp;
746: }
747:
748: cyberflex_fill_key_block (data + 28 + i*KEY_BLOCK_SIZE, 6 + i, 0, key);
749: }
750:
751: /* add the suffix */
752: data[28 + argc*KEY_BLOCK_SIZE] = 0;
753: data[28 + argc*KEY_BLOCK_SIZE + 1] = 0;
754:
755: for ( i = 0 ; i < KEY_BLOCK_SIZE * (argc + 2) + 2; i++ )
756: printf ("%02x ", data[i]);
757: printf ("\n");
758:
759: /* select 3f.00 (root) */
1.3 rees 760: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
761: printf("select root: %s\n", sectok_get_sw(sw));
1.2 rees 762: return -1;
1.3 rees 763: }
1.1 rees 764:
765: /* select 00.11 (key file) */
1.3 rees 766: if (sectok_selectfile(fd, cla, key_fid, &sw) < 0) {
767: printf("select key file: %s\n", sectok_get_sw(sw));
1.2 rees 768: return -1;
1.3 rees 769: }
1.1 rees 770:
771: /* all righty, now let's send it to the card! :) */
1.4 rees 772: rv = sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE * (argc + 2) + 2, data, 0, NULL, &sw);
773: if (!sectok_swOK(sw)) {
1.1 rees 774: /* error */
1.4 rees 775: printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1 rees 776: return -1;
777: }
778:
779: return 0;
780: }
781:
782: /* download AUT0 key into 3f.00/00.11 */
1.5 rees 783: int jsetpass(int ac, char *av[])
1.1 rees 784: {
1.5 rees 785: int sw, rv;
1.1 rees 786: unsigned char data[MAX_BUF_SIZE];
1.5 rees 787: unsigned char AUT0[20];
1.1 rees 788:
1.5 rees 789: if (!aut0_vfyd && jaut(0, NULL) < 0)
790: return -1;
1.1 rees 791:
1.5 rees 792: if (get_AUT0(ac, av, "Enter new AUT0 passphrase: ", AUT0) < 0)
793: return -1;
1.1 rees 794:
1.5 rees 795: cyberflex_fill_key_block (data, 0, 1, AUT0);
1.1 rees 796:
797: #if 0
798: /* add the suffix */
799: data[KEY_BLOCK_SIZE] = 0;
800: data[KEY_BLOCK_SIZE + 1] = 0;
801: #endif
802:
1.5 rees 803: #ifdef DEBUG
804: for (i = 0; i < KEY_BLOCK_SIZE; i++)
1.1 rees 805: printf ("%02x ", data[i]);
806: printf ("\n");
1.5 rees 807: #endif
1.1 rees 808:
809: /* select 3f.00 (root) */
1.3 rees 810: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2 rees 811: return -1;
1.1 rees 812:
813: /* select 00.11 (key file) */
1.3 rees 814: if (sectok_selectfile(fd, cla, key_fid, &sw) < 0)
1.2 rees 815: return -1;
1.1 rees 816:
817: /* all righty, now let's send it to the card! :) */
1.4 rees 818: rv = sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE, data, 0, NULL, &sw);
819: if (!sectok_swOK(sw)) {
1.1 rees 820: /* error */
1.4 rees 821: printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1 rees 822: return -1;
823: }
824:
825: return 0;
826: }
827:
828: /* download RSA private key into 3f.00/00.12 */
829: int cyberflex_load_rsa(int fd, unsigned char *buf)
830: {
1.3 rees 831: int rv, sw, i, j, tmp;
1.1 rees 832: static unsigned char key_fid[] = {0x00, 0x12};
833: static char *key_names[NUM_RSA_KEY_ELEMENTS]= {"p", "q", "1/p mod q",
834: "d mod (p-1)", "d mod (q-1)"};
835: unsigned char *key_elements[NUM_RSA_KEY_ELEMENTS];
836:
837: printf ("ca_load_rsa_priv buf=%s\n", buf);
838:
839: printf ("input 1024 bit RSA CRT key\n");
840: for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) {
841: printf ("%s (%d bit == %d byte) : ", key_names[i],
842: RSA_BIT_LEN/2, RSA_BIT_LEN/2/8);
843: key_elements[i] = (unsigned char *) malloc(RSA_BIT_LEN/8);
844: for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
845: fscanf (cmdf, "%02x", &tmp);
846: key_elements[i][j] = (unsigned char)tmp;
847: }
848: }
849:
850: #ifdef DEBUG
851: printf ("print RSA CRT key\n");
852: for (i = 0 ; i < NUM_RSA_KEY_ELEMENTS ; i ++ ) {
853: printf ("%s : ", key_names[i]);
854: for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
855: printf ("%02x ", key_elements[i][j]);
856: }
857: }
858: #endif
1.4 rees 859:
860: if (!aut0_vfyd)
861: jaut(0, NULL);
1.1 rees 862:
1.2 rees 863: rv = cyberflex_load_rsa_priv(fd, cla, key_fid, NUM_RSA_KEY_ELEMENTS, RSA_BIT_LEN,
1.3 rees 864: key_elements, &sw);
1.2 rees 865:
866: if (rv < 0)
1.3 rees 867: printf("load_rsa_priv: %s\n", sectok_get_sw(sw));
1.1 rees 868:
869: for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
870: free(key_elements[i]);
871: return rv;
872: }