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