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