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