Annotation of src/usr.bin/sectok/cmds.c, Revision 1.19
1.19 ! rees 1: /* $Id: cmds.c,v 1.10 2002/03/14 22:24:00 rees Exp $ */
1.1 rees 2:
3: /*
4: * Smartcard commander.
5: * Written by Jim Rees and others at University of Michigan.
6: */
7:
8: /*
9: copyright 2001
10: the regents of the university of michigan
11: all rights reserved
12:
13: permission is granted to use, copy, create derivative works
14: and redistribute this software and such derivative works
15: for any purpose, so long as the name of the university of
16: michigan is not used in any advertising or publicity
17: pertaining to the use or distribution of this software
18: without specific, written prior authorization. if the
19: above copyright notice or any other identification of the
20: university of michigan is included in any copy of any
21: portion of this software, then the disclaimer below must
22: also be included.
23:
24: this software is provided as is, without representation
25: from the university of michigan as to its fitness for any
26: purpose, and without warranty by the university of
27: michigan of any kind, either express or implied, including
28: without limitation the implied warranties of
29: merchantability and fitness for a particular purpose. the
30: regents of the university of michigan shall not be liable
31: for any damages, including special, indirect, incidental, or
32: consequential damages, with respect to any claim arising
33: out of or in connection with the use of the software, even
34: if it has been or is hereafter advised of the possibility of
35: such damages.
36: */
37:
1.15 rees 38: #ifdef __palmos__
39: #pragma pack(2)
40: #include <Common.h>
41: #include <System/SysAll.h>
42: #include <UI/UIAll.h>
43: #include <System/Unix/sys_types.h>
44: #include <System/Unix/unix_stdio.h>
45: #include <System/Unix/unix_stdlib.h>
46: #include <System/Unix/unix_string.h>
47: #include <string.h>
48: #include "getopt.h"
49: #include "sectok.h"
50: #include "field.h"
51: #else
1.1 rees 52: #include <unistd.h>
53: #include <stdlib.h>
54: #include <stdio.h>
55: #include <signal.h>
56: #include <string.h>
57: #include <sectok.h>
1.15 rees 58: #endif
1.1 rees 59:
60: #include "sc.h"
61:
1.15 rees 62: #define MAXFILELEN 0xffff
1.1 rees 63: #define CARDIOSIZE 200
64:
1.15 rees 65: struct dispatchtable dispatch_table[] = {
1.1 rees 66: /* Non-card commands */
1.4 rees 67: { "help", "[command]", help },
68: { "?", "[command]", help },
69: { "reset", "[ -1234ivf ]", reset },
70: { "open", "[ -1234ivf ]", reset },
71: { "close", "", dclose },
72: { "quit", "", quit },
1.1 rees 73:
74: /* 7816-4 commands */
1.4 rees 75: { "apdu", "[ -c class ] ins p1 p2 p3 data ...", apdu },
1.12 rees 76: { "fid", "[ -v ] fid/aid", selfid },
1.4 rees 77: { "isearch", "", isearch },
1.17 rees 78: { "csearch", "", csearch },
1.4 rees 79: { "class", "[ class ]", class },
1.18 rees 80: { "read", "[ -x ] [ filesize ]", dread },
1.4 rees 81: { "write", "input-filename", dwrite },
1.16 rees 82: { "challenge", "[ size ]", challenge },
1.18 rees 83: { "pin", "[ -k keyno ] [ PIN ]", vfypin },
1.19 ! rees 84: #ifndef __palmos__
1.18 rees 85: { "chpin", "[ -k keyno ]", chpin },
1.19 ! rees 86: #endif
1.1 rees 87:
88: /* Cyberflex commands */
1.9 rees 89: { "ls", "[ -l ]", ls },
1.14 rees 90: { "acl", "[ -x ] fid [ principal: r1 r2 ... ]", acl },
1.4 rees 91: { "create", "fid size", jcreate },
92: { "delete", "fid", jdelete },
93: { "jdefault", "[ -d ]", jdefault },
94: { "jatr", "", jatr },
95: { "jdata", "", jdata },
1.10 rees 96: { "login", "[ -d ] [ -k keyno ] [ -v ] [ -x hex-aut0 ]", jlogin },
1.15 rees 97: #ifndef __palmos__
1.6 rees 98: { "jaut", "", jaut },
1.10 rees 99: { "jload", "[ -p progID ] [ -c contID ] [ -s cont_size ] [ -i inst_size ] [ -a aid ] [ -v ] filename", jload },
1.15 rees 100: #endif
1.4 rees 101: { "junload", "[ -p progID ] [ -c contID ]", junload },
1.15 rees 102: #ifndef __palmos__
1.5 rees 103: { "setpass", "[ -d ] [ -x hex-aut0 ]", jsetpass },
1.15 rees 104: #endif
1.4 rees 105: { NULL, NULL, NULL }
1.1 rees 106: };
107:
1.16 rees 108: int curlen;
109:
1.1 rees 110: int dispatch(int ac, char *av[])
111: {
112: int i;
113:
1.2 rees 114: if (ac < 1)
115: return 0;
116:
1.1 rees 117: for (i = 0; dispatch_table[i].cmd; i++) {
1.2 rees 118: if (!strncmp(av[0], dispatch_table[i].cmd, strlen(av[0]))) {
1.1 rees 119: (dispatch_table[i].action) (ac, av);
120: break;
121: }
122: }
123: if (!dispatch_table[i].cmd) {
124: printf("unknown command \"%s\"\n", av[0]);
125: return -1;
126: }
127: return 0;
128: }
129:
130: int help(int ac, char *av[])
131: {
1.4 rees 132: int i, j;
1.1 rees 133:
1.4 rees 134: if (ac < 2) {
135: for (i = 0; dispatch_table[i].cmd; i++)
1.1 rees 136: printf("%s\n", dispatch_table[i].cmd);
1.4 rees 137: } else {
138: for (j = 1; j < ac; j++) {
139: for (i = 0; dispatch_table[i].cmd; i++)
1.14 rees 140: if (!strncmp(av[j], dispatch_table[i].cmd, strlen(av[j])))
1.4 rees 141: break;
142: if (dispatch_table[i].help)
143: printf("%s %s\n", dispatch_table[i].cmd, dispatch_table[i].help);
144: else
145: printf("no help on \"%s\"\n", av[j]);
146: }
1.1 rees 147: }
148:
149: return 0;
150: }
151:
152: int reset(int ac, char *av[])
153: {
1.3 rees 154: int i, n, oflags = 0, rflags = 0, vflag = 0, sw;
155: unsigned char atr[34];
156: struct scparam param;
1.1 rees 157:
158: optind = optreset = 1;
159:
1.12 rees 160: while ((i = getopt(ac, av, "0123ivf")) != -1) {
1.1 rees 161: switch (i) {
1.12 rees 162: case '0':
1.1 rees 163: case '1':
164: case '2':
165: case '3':
1.12 rees 166: port = i - '0';
1.1 rees 167: break;
168: case 'i':
1.3 rees 169: oflags |= STONOWAIT;
1.1 rees 170: break;
171: case 'v':
1.3 rees 172: vflag = 1;
1.1 rees 173: break;
174: case 'f':
1.7 rees 175: rflags |= STRFORCE;
1.1 rees 176: break;
177: }
178: }
179:
180: if (fd < 0) {
1.3 rees 181: fd = sectok_open(port, oflags, &sw);
1.1 rees 182: if (fd < 0) {
1.3 rees 183: sectok_print_sw(sw);
1.1 rees 184: return -1;
185: }
186: }
187:
1.4 rees 188: aut0_vfyd = 0;
189:
1.7 rees 190: n = sectok_reset(fd, rflags, atr, &sw);
1.16 rees 191: if (vflag) {
192: #ifdef __palmos__
193: hidefield(printfield->id);
194: sectok_parse_atr(fd, STRV, atr, n, ¶m);
195: showfield(printfield->id);
196: #else
1.11 rees 197: sectok_parse_atr(fd, STRV, atr, n, ¶m);
1.16 rees 198: #endif
199: }
1.7 rees 200: if (!sectok_swOK(sw)) {
201: printf("sectok_reset: %s\n", sectok_get_sw(sw));
202: dclose(0, NULL);
1.1 rees 203: return -1;
204: }
205:
206: return 0;
207: }
208:
209: int dclose(int ac, char *av[])
210: {
211: if (fd >= 0) {
1.11 rees 212: sectok_close(fd);
1.1 rees 213: fd = -1;
214: }
215: return 0;
216: }
217:
218: int quit(int ac, char *av[])
219: {
1.17 rees 220: dclose(0, NULL);
1.15 rees 221: #ifndef __palmos__
1.1 rees 222: exit(0);
1.15 rees 223: #else
224: return -1;
225: #endif
1.1 rees 226: }
227:
228: int apdu(int ac, char *av[])
229: {
1.9 rees 230: int i, ilen, olen, n, ins, xcl = cla, p1, p2, p3, sw;
231: unsigned char ibuf[256], obuf[256], *bp;
1.1 rees 232:
233: optind = optreset = 1;
234:
235: while ((i = getopt(ac, av, "c:")) != -1) {
236: switch (i) {
237: case 'c':
238: sscanf(optarg, "%x", &xcl);
239: break;
240: }
241: }
242:
243: if (ac - optind < 4) {
1.4 rees 244: printf("usage: apdu [ -c class ] ins p1 p2 p3 data ...\n");
1.1 rees 245: return -1;
246: }
247:
248: sscanf(av[optind++], "%x", &ins);
249: sscanf(av[optind++], "%x", &p1);
250: sscanf(av[optind++], "%x", &p2);
251: sscanf(av[optind++], "%x", &p3);
252:
1.9 rees 253: for (bp = ibuf, i = optind, ilen = 0; i < ac; i++) {
1.1 rees 254: sscanf(av[i], "%x", &n);
255: *bp++ = n;
1.9 rees 256: ilen++;
1.1 rees 257: }
258:
1.7 rees 259: if (fd < 0 && reset(0, NULL) < 0)
260: return -1;
1.1 rees 261:
1.9 rees 262: olen = (p3 && !ilen) ? p3 : sizeof obuf;
1.1 rees 263:
1.9 rees 264: n = sectok_apdu(fd, xcl, ins, p1, p2, ilen, ibuf, olen, obuf, &sw);
1.1 rees 265:
1.9 rees 266: sectok_dump_reply(obuf, n, sw);
1.1 rees 267:
268: return 0;
269: }
270:
271: int selfid(int ac, char *av[])
272: {
1.12 rees 273: unsigned char fid[16], obuf[256];
274: char *fname;
1.16 rees 275: int i, n, sel, fidlen, vflag = 0, sw;
1.1 rees 276:
1.11 rees 277: optind = optreset = 1;
278:
279: while ((i = getopt(ac, av, "v")) != -1) {
280: switch (i) {
281: case 'v':
1.16 rees 282: vflag = 1;
1.11 rees 283: break;
284: }
285: }
286:
1.12 rees 287: if (ac - optind == 0) {
288: /* No fid/aid given; select null aid (default loader for Cyberflex) */
289: sel = 4;
290: fidlen = 0;
291: } else {
292: fname = av[optind++];
293: if (!strcmp(fname, "..")) {
294: /* Special case ".." means parent */
295: sel = 3;
296: fidlen = 0;
297: } else if (strlen(fname) < 5) {
298: /* fid */
299: sel = 0;
300: fidlen = 2;
301: sectok_parse_fname(fname, fid);
302: } else {
303: /* aid */
304: sel = 4;
305: fidlen = sectok_parse_input(fname, fid, sizeof fid);
1.13 rees 306: if (fname[0] == '#') {
307: /* Prepend 0xfc to the aid to make it a "proprietary aid". */
308: fid[0] = 0xfc;
309: }
1.12 rees 310: }
1.1 rees 311: }
312:
1.7 rees 313: if (fd < 0 && reset(0, NULL) < 0)
314: return -1;
1.1 rees 315:
1.16 rees 316: n = sectok_apdu(fd, cla, 0xa4, sel, 0, fidlen, fid, 256, obuf, &sw);
1.11 rees 317: if (!sectok_swOK(sw)) {
318: printf("Select %02x%02x: %s\n", fid[0], fid[1], sectok_get_sw(sw));
1.2 rees 319: return -1;
1.12 rees 320: }
321:
1.16 rees 322: if (vflag && !n && sectok_r1(sw) == 0x61 && sectok_r2(sw)) {
1.12 rees 323: /* The card has out data but we must explicitly ask for it */
324: n = sectok_apdu(fd, cla, 0xc0, 0, 0, 0, NULL, sectok_r2(sw), obuf, &sw);
1.2 rees 325: }
1.1 rees 326:
1.16 rees 327: if (n >= 4) {
328: /* Some cards put the file length here. No guarantees. */
329: curlen = (obuf[2] << 8) | obuf[3];
330: }
331:
332: if (vflag)
1.11 rees 333: sectok_dump_reply(obuf, n, sw);
334:
1.3 rees 335: return 0;
336: }
337:
338: int isearch(int ac, char *av[])
339: {
1.11 rees 340: int i, r1, sw;
1.3 rees 341:
1.7 rees 342: if (fd < 0 && reset(0, NULL) < 0)
343: return -1;
1.3 rees 344:
345: /* find instructions */
1.11 rees 346: for (i = 0; i < 0xff; i += 2) {
347: sectok_apdu(fd, cla, i, 0, 0, 0, NULL, 0, NULL, &sw);
348: r1 = sectok_r1(sw);
349: if (r1 != 0x06 && r1 != 0x6d && r1 != 0x6e)
350: printf("%02x %s %s\n", i, sectok_get_ins(i), sectok_get_sw(sw));
1.17 rees 351: }
352: return 0;
353: }
354:
355: int csearch(int ac, char *av[])
356: {
357: int i, r1, sw;
358:
359: if (fd < 0 && reset(0, NULL) < 0)
360: return -1;
361:
362: /* find app classes */
363: for (i = 0; i <= 0xff; i++) {
364: sectok_apdu(fd, i, 0xa4, 0, 0, 2, root_fid, 0, NULL, &sw);
365: r1 = sectok_r1(sw);
366: if (r1 != 0x06 && r1 != 0x6d && r1 != 0x6e)
367: printf("%02x %s\n", i, sectok_get_sw(sw));
1.11 rees 368: }
1.1 rees 369: return 0;
370: }
371:
372: int class(int ac, char *av[])
373: {
374: if (ac > 1)
375: sscanf(av[1], "%x", &cla);
376: else
377: printf("Class %02x\n", cla);
378: return 0;
379: }
380:
381: int dread(int ac, char *av[])
382: {
1.15 rees 383: int i, n, col = 0, fsize, xflag = 0, sw;
384: unsigned int p3;
385: unsigned char buf[CARDIOSIZE+1];
1.1 rees 386:
1.10 rees 387: optind = optreset = 1;
388:
389: while ((i = getopt(ac, av, "x")) != -1) {
390: switch (i) {
391: case 'x':
392: xflag = 1;
393: break;
394: }
395: }
396:
1.16 rees 397: if (ac - optind < 1)
398: fsize = curlen;
399: else
400: sscanf(av[optind++], "%d", &fsize);
401:
402: if (!fsize) {
403: printf("please specify filesize\n");
1.1 rees 404: return -1;
405: }
406:
1.7 rees 407: if (fd < 0 && reset(0, NULL) < 0)
408: return -1;
1.1 rees 409:
1.15 rees 410: for (p3 = 0; fsize && p3 < MAXFILELEN; p3 += n) {
1.1 rees 411: n = (fsize < CARDIOSIZE) ? fsize : CARDIOSIZE;
1.10 rees 412: n = sectok_apdu(fd, cla, 0xb0, p3 >> 8, p3 & 0xff, 0, NULL, n, buf, &sw);
413: if (!sectok_swOK(sw)) {
1.11 rees 414: printf("ReadBinary: %s\n", sectok_get_sw(sw));
1.1 rees 415: break;
416: }
1.16 rees 417: #ifdef __palmos__
1.10 rees 418: if (xflag) {
1.16 rees 419: hidefield(printfield->id);
1.10 rees 420: for (i = 0; i < n; i++) {
421: printf("%02x ", buf[i]);
1.16 rees 422: if (col++ % 12 == 11)
1.10 rees 423: printf("\n");
424: }
1.16 rees 425: showfield(printfield->id);
1.15 rees 426: } else {
427: buf[n] = '\0';
428: printf("%s", buf);
1.16 rees 429: }
1.15 rees 430: #else
1.16 rees 431: if (xflag) {
432: for (i = 0; i < n; i++) {
433: printf("%02x ", buf[i]);
434: if (col++ % 16 == 15)
435: printf("\n");
436: }
437: } else
1.10 rees 438: fwrite(buf, 1, n, stdout);
1.15 rees 439: #endif
1.1 rees 440: fsize -= n;
441: }
1.10 rees 442:
443: if (xflag && col % 16 != 0)
444: printf("\n");
1.1 rees 445:
446: return 0;
447: }
448:
1.15 rees 449: #ifndef __palmos__
1.1 rees 450: int dwrite(int ac, char *av[])
451: {
1.11 rees 452: int n, p3, sw;
1.1 rees 453: FILE *f;
454: unsigned char buf[CARDIOSIZE];
455:
456: if (ac != 2) {
457: printf("usage: write input-filename\n");
458: return -1;
459: }
460:
1.7 rees 461: if (fd < 0 && reset(0, NULL) < 0)
462: return -1;
1.1 rees 463:
464: f = fopen(av[1], "r");
465: if (!f) {
466: printf("can't open %s\n", av[1]);
467: return -1;
468: }
469:
470: n = 0;
471: while ((p3 = fread(buf, 1, CARDIOSIZE, f)) > 0) {
1.11 rees 472: sectok_apdu(fd, cla, 0xd6, n >> 8, n & 0xff, p3, buf, 0, NULL, &sw);
473: if (!sectok_swOK(sw)) {
474: printf("UpdateBinary: %s\n", sectok_get_sw(sw));
1.1 rees 475: break;
476: }
477: n += p3;
478: }
479: fclose(f);
480:
481: return (n ? 0 : -1);
482: }
1.16 rees 483: #else
484: int dwrite(int ac, char *av[])
485: {
486: int n, sw;
487: char *s;
488:
489: if (ac != 2) {
490: printf("usage: write text\n");
491: return -1;
492: }
493: s = av[1];
494: n = strlen(s);
495: sectok_apdu(fd, cla, 0xd6, 0, 0, n, s, 0, NULL, &sw);
496: if (!sectok_swOK(sw)) {
497: printf("UpdateBinary: %s\n", sectok_get_sw(sw));
498: return -1;
499: }
500: return 0;
501: }
1.15 rees 502: #endif
1.16 rees 503:
504: int challenge(int ac, char *av[])
505: {
506: int n = 8, sw;
507: unsigned char buf[256];
508:
509: if (ac > 1)
510: n = atoi(av[1]);
511:
512: n = sectok_apdu(fd, cla, 0x84, 0, 0, 0, NULL, n, buf, &sw);
513:
514: if (!sectok_swOK(sw)) {
515: printf("GetChallenge: %s\n", sectok_get_sw(sw));
516: return -1;
517: }
518:
519: sectok_dump_reply(buf, n, sw);
1.18 rees 520: return 0;
521: }
522:
523: int vfypin(int ac, char *av[])
524: {
525: int keyno = 1, i, sw;
526: char *pin;
527:
528: optind = optreset = 1;
529:
530: while ((i = getopt(ac, av, "k:")) != -1) {
531: switch (i) {
532: case 'k':
533: keyno = atoi(optarg);
534: break;
535: }
536: }
537:
538: if (ac - optind >= 1)
539: pin = av[optind++];
1.19 ! rees 540: else {
! 541: #ifndef __palmos__
1.18 rees 542: pin = getpass("Enter PIN: ");
1.19 ! rees 543: #else
! 544: printf("usage: pin PIN\n");
! 545: return -1;
! 546: #endif
! 547: }
1.18 rees 548:
549: sectok_apdu(fd, cla, 0x20, 0, keyno, strlen(pin), pin, 0, NULL, &sw);
550: bzero(pin, strlen(pin));
551:
552: if (!sectok_swOK(sw)) {
553: printf("VerifyCHV: %s\n", sectok_get_sw(sw));
554: return -1;
555: }
556: return 0;
557: }
558:
1.19 ! rees 559: #ifndef __palmos__
1.18 rees 560: int chpin(int ac, char *av[])
561: {
562: int keyno = 1, i, sw;
563: char pin[255];
564:
565: optind = optreset = 1;
566:
567: while ((i = getopt(ac, av, "k:")) != -1) {
568: switch (i) {
569: case 'k':
570: keyno = atoi(optarg);
571: break;
572: }
573: }
574:
575: strcpy(pin, getpass("Enter Old PIN: "));
576: strcat(pin, getpass("Enter New PIN: "));
577:
578: sectok_apdu(fd, cla, 0x24, 0, keyno, strlen(pin), pin, 0, NULL, &sw);
579: bzero(pin, strlen(pin));
580:
581: if (!sectok_swOK(sw)) {
582: printf("UpdateCHV: %s\n", sectok_get_sw(sw));
583: return -1;
584: }
1.16 rees 585: return 0;
586: }
1.19 ! rees 587: #endif