Annotation of src/usr.bin/sectok/cyberflex.c, Revision 1.5
1.5 ! rees 1: /* $Id: cyberflex.c,v 1.4 2001/07/16 21:02:21 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.4 rees 128: int jaut(int ac, char *av[])
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.4 rees 167: }
168:
1.1 rees 169: int jdefault(int ac, char *av[])
170: {
171: unsigned char buf[8];
1.4 rees 172: int i, p1 = 4, sw;
1.1 rees 173:
174: optind = optreset = 1;
175:
176: while ((i = getopt(ac, av, "d")) != -1) {
177: switch (i) {
178: case 'd':
179: p1 = 5;
180: break;
181: }
182: }
183:
184: if (fd < 0)
185: reset(0, NULL);
1.4 rees 186: if (!aut0_vfyd)
187: jaut(0, NULL);
1.1 rees 188:
1.4 rees 189: sectok_apdu(fd, cla, 0x08, p1, 0, 0, buf, 0, NULL, &sw);
190: if (!sectok_swOK(sw)) {
1.1 rees 191: /* error */
1.4 rees 192: sectok_print_sw(sw);
1.1 rees 193: return -1;
194: }
195: return 0;
196: }
197:
198: int jatr(int ac, char *av[])
199: {
200: unsigned char buf[64];
1.4 rees 201: int n = 0, sw;
1.1 rees 202:
203: if (fd < 0)
204: reset(0, NULL);
205:
206: buf[n++] = 0x90;
207: buf[n++] = 0x94; /* TA1 */
208: buf[n++] = 0x40; /* TD1 */
209: buf[n++] = 0x28; /* TC2 (WWT=4sec) */
210: if (ac > optind) {
211: /* set historical bytes from command line */
212: n += parse_input(av[1], &buf[n], 15);
213: } else {
214: /* no historical bytes given, use default */
215: memmove(&buf[n], DFLTATR, sizeof DFLTATR);
216: n += sizeof DFLTATR;
217: }
218: buf[0] |= ((n - 2) & 0xf);
1.4 rees 219: sectok_apdu(fd, cla, 0xfa, 0, 0, n, buf, 0, NULL, &sw);
220: if (!sectok_swOK(sw)) {
1.1 rees 221: /* error */
1.4 rees 222: sectok_print_sw(sw);
1.1 rees 223: return -1;
224: }
225: return 0;
226: }
227:
228: int jdata(int ac, char *av[])
229: {
230: unsigned char buf[32];
1.4 rees 231: int i, sw;
1.1 rees 232:
233: if (fd < 0)
234: reset(0, NULL);
235:
1.4 rees 236: sectok_apdu(fd, cla, 0xca, 0, 1, 0, NULL, 0x16, buf, &sw);
237: if (sectok_swOK(sw)) {
1.1 rees 238: printf("serno ");
239: for (i = 0; i < 6; i++)
240: printf("%02x ", buf[i]);
241: printf("batch %02x sver %d.%02d ", buf[6], buf[7], buf[8]);
242: if (buf[9] == 0x0c)
243: printf("augmented ");
244: else if (buf[9] == 0x0b)
245: ;
246: else
247: printf("unknown ");
248: printf("crypto %9.9s class %02x\n", &buf[10], buf[19]);
249: } else {
250: /* error */
1.4 rees 251: sectok_print_sw(sw);
1.1 rees 252: }
253: return 0;
254: }
255:
256: #define JDIRSIZE 40
257:
258: int ls(int ac, char *av[])
259: {
1.4 rees 260: int p2, f0, f1, sw;
1.1 rees 261: char ftype[32], fname[6];
262: unsigned char buf[JDIRSIZE];
263:
264: if (fd < 0)
265: reset(0, NULL);
266:
267: for (p2 = 0; ; p2++) {
1.4 rees 268: if (sectok_apdu(fd, cla, 0xa8, 0, p2, 0, NULL, JDIRSIZE, buf, &sw) < 0)
1.1 rees 269: break;
1.4 rees 270: if (!sectok_swOK(sw))
1.1 rees 271: break;
272: f0 = buf[4];
273: f1 = buf[5];
274: if (f0 == 0xff || f0 + f1 == 0)
275: continue;
276: sectok_fmt_fid(fname, f0, f1);
277: if (buf[6] == 1)
278: /* root */
279: sprintf(ftype, "root");
280: else if (buf[6] == 2) {
281: /* DF */
282: if (buf[12] == 27)
283: sprintf(ftype, "%s %s", appstat[buf[10]], apptype[buf[9]]);
284: else
285: sprintf(ftype, "directory");
286: } else if (buf[6] == 4)
287: /* EF */
288: sprintf(ftype, "%s", filestruct[buf[13]]);
289: printf("%4s %5d %s\n", fname, (buf[2] << 8) | buf[3], ftype);
290: }
291: return 0;
292: }
293:
1.3 rees 294: int jcreate(int ac, char *av[])
295: {
296: unsigned char fid[2];
297: int sw, fsize;
298:
299: if (ac != 3) {
300: printf("usage: create fid size\n");
301: return -1;
302: }
303:
304: sectok_parse_fname(av[1], fid);
305: sscanf(av[2], "%d", &fsize);
306:
307: if (fd < 0)
308: reset(0, NULL);
1.4 rees 309: if (!aut0_vfyd)
310: jaut(0, NULL);
1.3 rees 311:
312: if (cyberflex_create_file(fd, cla, fid, fsize, 3, &sw) < 0) {
313: printf("create_file: %s\n", sectok_get_sw(sw));
314: return -1;
315: }
316:
317: return 0;
318: }
319:
320: int jdelete(int ac, char *av[])
321: {
322: unsigned char fid[2];
323: int sw;
324:
325: if (ac != 2) {
326: printf("usage: delete fid\n");
327: return -1;
328: }
329:
330: sectok_parse_fname(av[1], fid);
331:
332: if (fd < 0)
333: reset(0, NULL);
1.4 rees 334: if (!aut0_vfyd)
335: jaut(0, NULL);
1.3 rees 336:
337: if (cyberflex_delete_file(fd, cla, fid, &sw) < 0) {
338: printf("delete_file: %s\n", sectok_get_sw(sw));
339: return -1;
340: }
341:
342: return 0;
343: }
344:
1.1 rees 345: #define MAX_BUF_SIZE 256
346: #define MAX_APP_SIZE 4096
347: #define MAX_APDU_SIZE 0xfa
348: #define BLOCK_SIZE 8
349: #define MAXTOKENS 16
350:
351: unsigned char *app_name;
352: unsigned char progID[2], contID[2], aid[MAX_BUF_SIZE];
353: int cont_size, inst_size;
354: int aid_len;
355:
356: int analyze_load_options(int ac, char *av[])
357: {
358: int i, rv;
359:
360: progID[0] = 0x77;
361: progID[1] = 0x77;
362: contID[0] = 0x77;
363: contID[1] = 0x78;
364: cont_size = 1152;
365: inst_size = 1024;
366: aid_len = 5;
367:
368: for (i = 0 ; i < 16 ; i ++)
369: aid[i] = 0x77;
370:
371: /* applet file name */
372: app_name = av[ac - 1];
373:
374: optind = optreset = 1;
375:
376: /* switch on options */
377: while (1) {
378: rv = getopt (ac, av, "p:c:s:i:a:");
379: if (rv == -1) break;
380: /*printf ("rv=%c, optarg=%s\n", rv, optarg);*/
381: switch (rv) {
382: case 'p':
383: parse_input(optarg, progID, 2);
384: break;
385: case 'c':
386: parse_input(optarg, contID, 2);
387: break;
388: case 's':
389: sscanf(optarg, "%d", &cont_size);
390: break;
391: case 'i':
392: sscanf(optarg, "%d", &inst_size);
393: break;
394: case 'a':
395: aid_len = parse_input(optarg, aid, sizeof aid);
396: /*printf ("aid_len = %d\n", aid_len);*/
397: break;
398: default:
399: printf ("unknown option. command aborted.\n");
400: return -1;
401: }
402: }
403:
404: return 0;
405: }
406:
407: int jload(int ac, char *av[])
408: {
409: char progname[5], contname[5];
410: unsigned char app_data[MAX_APP_SIZE],
411: data[MAX_BUF_SIZE];
1.4 rees 412: int i, j, fd_app, size, rv, sw;
1.1 rees 413: des_cblock tmp;
414: des_key_schedule schedule;
415:
416: if (analyze_load_options(ac, av) < 0)
417: return -1;
418:
419: if (fd < 0)
420: reset(0, NULL);
1.4 rees 421: if (!aut0_vfyd)
422: jaut(0, NULL);
1.1 rees 423:
424: sectok_fmt_fid(progname, progID[0], progID[1]);
425: sectok_fmt_fid(contname, contID[0], contID[1]);
426:
427: printf ("applet file \"%s\"\n", app_name);
428: printf ("program ID %s\n", progname);
429: printf ("container ID %s\n", contname);
430: printf ("instance container size %d\n", cont_size);
431: printf ("instance data size %d\n", inst_size);
432: printf ("AID ");
433: for (i = 0 ; i < aid_len ; i ++ )
434: printf ("%02x", (unsigned char)aid[i]);
435: printf ("\n");
436:
437: /* open the input file */
438: fd_app = open (app_name, O_RDONLY, NULL);
439: if (fd_app == -1) {
440: fprintf (stderr, "cannot open file \"%s\"\n", app_name);
441: return -1;
442: }
443:
444: /* read the input file */
445: size = read (fd_app, app_data, MAX_APP_SIZE);
446: if (size == 0) {
447: fprintf (stderr, "file %s size 0??\n", app_name);
448: return -1;
449: }
450: if (size == -1) {
451: fprintf (stderr, "error reading file %s\n", app_name);
452: return -1;
453: }
454:
455: /*printf ("file size %d\n", size);*/
456:
457: /* size must be able to be divided by BLOCK_SIZE */
458: if (size % BLOCK_SIZE != 0) {
459: fprintf (stderr, "file (%s) size cannot be divided by BLOCK_SIZE.\n",
460: app_name);
461: return -1;
462: }
463:
464: /* compute the signature of the applet */
465: /* initialize the result buffer */
466: for (j = 0; j < BLOCK_SIZE; j++ ) {
467: tmp[j] = 0;
468: }
469:
470: /* chain. DES encrypt one block, XOR the cyphertext with the next block,
471: ... continues until the end of the buffer */
472:
473: des_set_key (&app_key, schedule);
474:
475: for (i = 0; i < size/BLOCK_SIZE; i++) {
476: for (j = 0; j < BLOCK_SIZE; j++ ){
477: tmp[j] = tmp[j] ^ app_data[i*BLOCK_SIZE + j];
478: }
479: des_ecb_encrypt (&tmp, &tmp, schedule, DES_ENCRYPT);
480: }
481:
482: /* print out the signature */
483: printf ("signature ");
484: for (j = 0; j < BLOCK_SIZE; j++ ) {
485: printf ("%02x", tmp[j]);
486: }
487: printf ("\n");
488:
489: /* select the default loader */
1.4 rees 490: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
491: if (!sectok_swOK(sw)) {
1.1 rees 492: /* error */
1.4 rees 493: printf("can't select default loader: %s\n", sectok_get_sw(sw));
1.1 rees 494: return -1;
495: }
496:
497: /* select 3f.00 (root) */
1.3 rees 498: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2 rees 499: return -1;
1.1 rees 500:
501: /* create program file */
1.3 rees 502: if (cyberflex_create_file(fd, cla, progID, size, 3, &sw) < 0) {
1.1 rees 503: /* error */
1.3 rees 504: printf("can't create %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 505: return -1;
506: }
507:
508: /* update binary */
509: for (i = 0; i < size; i += MAX_APDU_SIZE) {
510: int send_size;
511:
512: /* compute the size to be sent */
513: if (size - i > MAX_APDU_SIZE) send_size = MAX_APDU_SIZE;
514: else send_size = size - i;
515:
1.4 rees 516: rv = sectok_apdu(fd, cla, 0xd6, i / 256, i % 256, send_size, app_data + i, 0, NULL, &sw);
1.1 rees 517:
1.4 rees 518: if (!sectok_swOK(sw)) {
1.1 rees 519: /* error */
1.4 rees 520: printf("updating binary %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 521: return -1;
522: }
523: }
524:
525: /* manage program .. validate */
1.4 rees 526: rv = sectok_apdu(fd, cla, 0x0a, 01, 0, 0x08, tmp, 0, NULL, &sw);
1.1 rees 527:
1.4 rees 528: if (!sectok_swOK(sw)) {
1.1 rees 529: /* error */
1.4 rees 530: printf("validating applet in %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 531: return -1;
532: }
533:
534: /* select the default loader */
1.4 rees 535: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
536: if (!sectok_swOK(sw)) {
1.1 rees 537: /* error */
1.4 rees 538: printf("selecting default loader: %s\n", sectok_get_sw(sw));
1.1 rees 539: return -1;
540: }
541:
542: /* execute method -- call the install() method in the cardlet.
543: cardlet type 01 (applet, not application)
544: program ID (7777)
545: instance container size (0800 (1152))
546: instance container ID (7778)
547: instance data size (0400 (1024))
548: AID length (0005 (5 byte))
549: AID (7777777777) */
550:
551: data[0] = 0x01; /* cardlet type = 1 (applet, not application) */
552: data[1] = progID[0]; /* FID, upper */
553: data[2] = progID[1]; /* FID, lower */
554: data[3] = cont_size / 256; /* instance container size 0x0800 (1152) byte, upper */
555: data[4] = cont_size % 256; /* instance container size 0x0800 (1152) byte, lower */
556: data[5] = contID[0]; /* container ID (7778), upper */
557: data[6] = contID[1]; /* container ID (7778), lower */
558: data[7] = inst_size / 256; /* instance size 0x0400 (1024) byte, upper */
559: data[8] = inst_size % 256; /* instance size 0x0400 (1024) byte, lower */
560: data[9] = 0x00; /* AID length 0x0005, upper */
561: data[10] = aid_len; /* AID length 0x0005, lower */
562: for (i = 0; i < aid_len; i++) data[i + 11] = (unsigned int)aid[i];
563: /* AID (7777777777) */
564:
1.4 rees 565: rv = sectok_apdu(fd, cla, 0x0c, 0x13, 0, 11 + aid_len, data, 0, NULL, &sw);
566: if (!sectok_swOK(sw)) {
1.1 rees 567: /* error */
1.4 rees 568: printf("executing install() method in applet %s: %s\n", progname, sectok_get_sw(sw));
1.1 rees 569: return -1;
570: }
571:
572: /* That's it! :) */
573: return 0;
574: }
575:
576: int junload(int ac, char *av[])
577: {
578: char progname[5], contname[5];
1.4 rees 579: int sw, rv;
1.1 rees 580:
581: if (analyze_load_options(ac, av) < 0)
582: return -1;
583:
584: if (fd < 0)
585: reset(0, NULL);
1.4 rees 586: if (!aut0_vfyd)
587: jaut(0, NULL);
1.1 rees 588:
589: sectok_fmt_fid(progname, progID[0], progID[1]);
590: sectok_fmt_fid(contname, contID[0], contID[1]);
591:
592: printf ("program ID %s\n", progname);
593: printf ("container ID %s\n", contname);
594:
595: /* select 3f.00 (root) */
1.3 rees 596: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
597: printf("can't select root: %s\n", sectok_get_sw(sw));
1.2 rees 598: return -1;
1.3 rees 599: }
1.1 rees 600:
601: /* select program file */
1.3 rees 602: if (sectok_selectfile(fd, cla, progID, &sw) >= 0) {
1.1 rees 603:
1.2 rees 604: /* manage program -- reset */
1.4 rees 605: rv = sectok_apdu(fd, cla, 0x0a, 02, 0, 0, NULL, 0, NULL, &sw);
606: if (!sectok_swOK(sw)) {
1.2 rees 607: /* error */
1.4 rees 608: printf("resetting applet: %s\n", sectok_get_sw(sw));
1.2 rees 609: }
1.1 rees 610:
1.2 rees 611: /* delete program file */
1.3 rees 612: if (cyberflex_delete_file(fd, cla, progID, &sw) < 0)
613: printf("delete_file %s: %s\n", progname, sectok_get_sw(sw));
1.2 rees 614: } else
615: printf ("no program file... proceed to delete data container\n");
1.1 rees 616:
617: /* delete data container */
1.3 rees 618: if (cyberflex_delete_file(fd, cla, contID, &sw) < 0)
619: printf("delete_file %s: %s\n", contname, sectok_get_sw(sw));
1.1 rees 620:
621: return 0;
622: }
623:
624: int jselect(int ac, char *av[])
625: {
1.4 rees 626: int i, sw, rv;
1.1 rees 627: unsigned char data[MAX_BUF_SIZE];
628:
629: optind = optreset = 1;
630:
631: if (analyze_load_options(ac, av) < 0)
632: return -1;
633:
634: if (fd < 0)
635: reset(0, NULL);
636:
637: printf ("select applet\n");
638: printf ("AID ");
639: for (i = 0 ; i < aid_len ; i ++ )
640: printf ("%02x", (unsigned char)aid[i]);
641: printf ("\n");
642:
643: /* select the cardlet (7777777777) */
644: for (i = 0; i < aid_len; i++) data[i] = (unsigned char)aid[i];
645: /* quick hack in select_applet()
646: even with F0 card, select applet APDU (00 a4 04)
647: only accepts class byte 00 (not f0) */
648:
1.4 rees 649: rv = sectok_apdu(fd, cla, 0xa4, 0x04, 0, aid_len, data, 0, NULL, &sw);
650: if (!sectok_swOK(sw)) {
1.1 rees 651: /* error */
652: printf ("selecting the cardlet: ");
653: for (i = 0 ; i < aid_len ; i ++ ) {
654: printf ("%02x", (unsigned char)aid[i]);
655: }
656: printf ("\n");
1.4 rees 657: sectok_print_sw(sw);
1.1 rees 658: return -1;
659: }
660:
661: return 0;
662: }
663:
664: int jdeselect(int ac, char *av[])
665: {
1.3 rees 666: int sw;
1.1 rees 667:
668: if (fd < 0)
669: reset(0, NULL);
670:
1.3 rees 671: sectok_apdu(fd, cla, 0xa4, 0x04, 0, 0, NULL, 0, NULL, &sw);
672: if (!sectok_swOK(sw)) {
1.1 rees 673: /* error */
1.3 rees 674: printf("selecting default loader: %s\n", sectok_get_sw(sw));
1.1 rees 675: return -1;
676: }
677:
678: return 0;
679: }
680:
681: #define DELIMITER " :\t\n"
682: #define KEY_BLOCK_SIZE 14
683:
684: /* download DES keys into 3f.00/00.11 */
685: int cyberflex_load_key (int fd, unsigned char *buf)
686: {
1.4 rees 687: int sw, rv, argc = 0, i, j, tmp;
1.1 rees 688: unsigned char *token;
689: unsigned char data[MAX_BUF_SIZE];
690: unsigned char key[BLOCK_SIZE];
691:
692: #if 0
693: /* select the default loader */
694: rv = scwrite(fd, cla, 0xa4, 0x04, 0, 0x00, NULL, &r1, &r2);
695: if (r1 != 0x90 && r1 != 0x61) {
696: // error
697: printf ("selecting the default loader: ");
698: print_r1r2 (r1, r2);
699: return -1;
700: }
701: #endif
702:
703: printf ("ca_load_key buf=%s\n", buf);
704: token = strtok (buf, DELIMITER);
705: token = strtok (NULL, DELIMITER);
706: if (token == NULL) {
707: printf ("Usage: jk number_of_keys\n");
708: return -1;
709: }
710: argc = atoi (token);
711:
712: if (argc > 2) {
713: printf ("current Cyberflex Access cannot download more than 2 keys to the key file. Sorry. :(\n");
714: return -1;
715: }
716:
717: if (argc < 0) {
718: printf ("you want to down load %d keys??\n", argc);
719: return -1;
720: }
721:
1.4 rees 722: if (!aut0_vfyd)
723: jaut(0, NULL);
724:
1.1 rees 725: /* Now let's do it. :) */
726:
727: /* add the AUT0 */
1.5 ! rees 728: cyberflex_fill_key_block (data, 0, 1, DFLTAUT0);
1.1 rees 729:
730: /* add the applet sign key */
731: cyberflex_fill_key_block (data+KEY_BLOCK_SIZE, 5, 0, app_key);
732:
733: /* then add user defined keys */
734: for ( i = 0 ; i < argc ; i++ ) {
735: printf ("key %d : ", i);
736: for ( j = 0 ; j < BLOCK_SIZE ; j++ ) {
737: fscanf (cmdf, "%02x", &tmp);
738: key[j] = (unsigned char)tmp;
739: }
740:
741: cyberflex_fill_key_block (data + 28 + i*KEY_BLOCK_SIZE, 6 + i, 0, key);
742: }
743:
744: /* add the suffix */
745: data[28 + argc*KEY_BLOCK_SIZE] = 0;
746: data[28 + argc*KEY_BLOCK_SIZE + 1] = 0;
747:
748: for ( i = 0 ; i < KEY_BLOCK_SIZE * (argc + 2) + 2; i++ )
749: printf ("%02x ", data[i]);
750: printf ("\n");
751:
752: /* select 3f.00 (root) */
1.3 rees 753: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0) {
754: printf("select root: %s\n", sectok_get_sw(sw));
1.2 rees 755: return -1;
1.3 rees 756: }
1.1 rees 757:
758: /* select 00.11 (key file) */
1.3 rees 759: if (sectok_selectfile(fd, cla, key_fid, &sw) < 0) {
760: printf("select key file: %s\n", sectok_get_sw(sw));
1.2 rees 761: return -1;
1.3 rees 762: }
1.1 rees 763:
764: /* all righty, now let's send it to the card! :) */
1.4 rees 765: rv = sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE * (argc + 2) + 2, data, 0, NULL, &sw);
766: if (!sectok_swOK(sw)) {
1.1 rees 767: /* error */
1.4 rees 768: printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1 rees 769: return -1;
770: }
771:
772: return 0;
773: }
774:
775: /* download AUT0 key into 3f.00/00.11 */
1.5 ! rees 776: int jsetpass(int ac, char *av[])
1.1 rees 777: {
1.5 ! rees 778: int sw, rv;
1.1 rees 779: unsigned char data[MAX_BUF_SIZE];
1.5 ! rees 780: unsigned char AUT0[20];
1.1 rees 781:
1.5 ! rees 782: if (!aut0_vfyd && jaut(0, NULL) < 0)
! 783: return -1;
1.1 rees 784:
1.5 ! rees 785: if (get_AUT0(ac, av, "Enter new AUT0 passphrase: ", AUT0) < 0)
! 786: return -1;
1.1 rees 787:
1.5 ! rees 788: cyberflex_fill_key_block (data, 0, 1, AUT0);
1.1 rees 789:
790: #if 0
791: /* add the suffix */
792: data[KEY_BLOCK_SIZE] = 0;
793: data[KEY_BLOCK_SIZE + 1] = 0;
794: #endif
795:
1.5 ! rees 796: #ifdef DEBUG
! 797: for (i = 0; i < KEY_BLOCK_SIZE; i++)
1.1 rees 798: printf ("%02x ", data[i]);
799: printf ("\n");
1.5 ! rees 800: #endif
1.1 rees 801:
802: /* select 3f.00 (root) */
1.3 rees 803: if (sectok_selectfile(fd, cla, root_fid, &sw) < 0)
1.2 rees 804: return -1;
1.1 rees 805:
806: /* select 00.11 (key file) */
1.3 rees 807: if (sectok_selectfile(fd, cla, key_fid, &sw) < 0)
1.2 rees 808: return -1;
1.1 rees 809:
810: /* all righty, now let's send it to the card! :) */
1.4 rees 811: rv = sectok_apdu(fd, cla, 0xd6, 0, 0, KEY_BLOCK_SIZE, data, 0, NULL, &sw);
812: if (!sectok_swOK(sw)) {
1.1 rees 813: /* error */
1.4 rees 814: printf("writing the key file 00.11: %s\n", sectok_get_sw(sw));
1.1 rees 815: return -1;
816: }
817:
818: return 0;
819: }
820:
821: /* download RSA private key into 3f.00/00.12 */
822: int cyberflex_load_rsa(int fd, unsigned char *buf)
823: {
1.3 rees 824: int rv, sw, i, j, tmp;
1.1 rees 825: static unsigned char key_fid[] = {0x00, 0x12};
826: static char *key_names[NUM_RSA_KEY_ELEMENTS]= {"p", "q", "1/p mod q",
827: "d mod (p-1)", "d mod (q-1)"};
828: unsigned char *key_elements[NUM_RSA_KEY_ELEMENTS];
829:
830: printf ("ca_load_rsa_priv buf=%s\n", buf);
831:
832: printf ("input 1024 bit RSA CRT key\n");
833: for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) {
834: printf ("%s (%d bit == %d byte) : ", key_names[i],
835: RSA_BIT_LEN/2, RSA_BIT_LEN/2/8);
836: key_elements[i] = (unsigned char *) malloc(RSA_BIT_LEN/8);
837: for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
838: fscanf (cmdf, "%02x", &tmp);
839: key_elements[i][j] = (unsigned char)tmp;
840: }
841: }
842:
843: #ifdef DEBUG
844: printf ("print RSA CRT key\n");
845: for (i = 0 ; i < NUM_RSA_KEY_ELEMENTS ; i ++ ) {
846: printf ("%s : ", key_names[i]);
847: for ( j = 0 ; j < RSA_BIT_LEN/8/2 ; j++ ) {
848: printf ("%02x ", key_elements[i][j]);
849: }
850: }
851: #endif
1.4 rees 852:
853: if (!aut0_vfyd)
854: jaut(0, NULL);
1.1 rees 855:
1.2 rees 856: rv = cyberflex_load_rsa_priv(fd, cla, key_fid, NUM_RSA_KEY_ELEMENTS, RSA_BIT_LEN,
1.3 rees 857: key_elements, &sw);
1.2 rees 858:
859: if (rv < 0)
1.3 rees 860: printf("load_rsa_priv: %s\n", sectok_get_sw(sw));
1.1 rees 861:
862: for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
863: free(key_elements[i]);
864: return rv;
865: }