Annotation of src/usr.bin/sectok/cmds.c, Revision 1.16
1.16 ! rees 1: /* $Id: cmds.c,v 1.6 2001/08/15 19:41:05 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 },
78: { "class", "[ class ]", class },
1.10 rees 79: { "read", "[ -x ] filesize", dread },
1.4 rees 80: { "write", "input-filename", dwrite },
1.16 ! rees 81: { "challenge", "[ size ]", challenge },
1.1 rees 82:
83: /* Cyberflex commands */
1.9 rees 84: { "ls", "[ -l ]", ls },
1.14 rees 85: { "acl", "[ -x ] fid [ principal: r1 r2 ... ]", acl },
1.4 rees 86: { "create", "fid size", jcreate },
87: { "delete", "fid", jdelete },
88: { "jdefault", "[ -d ]", jdefault },
89: { "jatr", "", jatr },
90: { "jdata", "", jdata },
1.10 rees 91: { "login", "[ -d ] [ -k keyno ] [ -v ] [ -x hex-aut0 ]", jlogin },
1.15 rees 92: #ifndef __palmos__
1.6 rees 93: { "jaut", "", jaut },
1.10 rees 94: { "jload", "[ -p progID ] [ -c contID ] [ -s cont_size ] [ -i inst_size ] [ -a aid ] [ -v ] filename", jload },
1.15 rees 95: #endif
1.4 rees 96: { "junload", "[ -p progID ] [ -c contID ]", junload },
1.15 rees 97: #ifndef __palmos__
1.5 rees 98: { "setpass", "[ -d ] [ -x hex-aut0 ]", jsetpass },
1.15 rees 99: #endif
1.4 rees 100: { NULL, NULL, NULL }
1.1 rees 101: };
102:
1.16 ! rees 103: int curlen;
! 104:
1.1 rees 105: int dispatch(int ac, char *av[])
106: {
107: int i;
108:
1.2 rees 109: if (ac < 1)
110: return 0;
111:
1.1 rees 112: for (i = 0; dispatch_table[i].cmd; i++) {
1.2 rees 113: if (!strncmp(av[0], dispatch_table[i].cmd, strlen(av[0]))) {
1.1 rees 114: (dispatch_table[i].action) (ac, av);
115: break;
116: }
117: }
118: if (!dispatch_table[i].cmd) {
119: printf("unknown command \"%s\"\n", av[0]);
120: return -1;
121: }
122: return 0;
123: }
124:
125: int help(int ac, char *av[])
126: {
1.4 rees 127: int i, j;
1.1 rees 128:
1.4 rees 129: if (ac < 2) {
130: for (i = 0; dispatch_table[i].cmd; i++)
1.1 rees 131: printf("%s\n", dispatch_table[i].cmd);
1.4 rees 132: } else {
133: for (j = 1; j < ac; j++) {
134: for (i = 0; dispatch_table[i].cmd; i++)
1.14 rees 135: if (!strncmp(av[j], dispatch_table[i].cmd, strlen(av[j])))
1.4 rees 136: break;
137: if (dispatch_table[i].help)
138: printf("%s %s\n", dispatch_table[i].cmd, dispatch_table[i].help);
139: else
140: printf("no help on \"%s\"\n", av[j]);
141: }
1.1 rees 142: }
143:
144: return 0;
145: }
146:
147: int reset(int ac, char *av[])
148: {
1.3 rees 149: int i, n, oflags = 0, rflags = 0, vflag = 0, sw;
150: unsigned char atr[34];
151: struct scparam param;
1.1 rees 152:
153: optind = optreset = 1;
154:
1.12 rees 155: while ((i = getopt(ac, av, "0123ivf")) != -1) {
1.1 rees 156: switch (i) {
1.12 rees 157: case '0':
1.1 rees 158: case '1':
159: case '2':
160: case '3':
1.12 rees 161: port = i - '0';
1.1 rees 162: break;
163: case 'i':
1.3 rees 164: oflags |= STONOWAIT;
1.1 rees 165: break;
166: case 'v':
1.3 rees 167: vflag = 1;
1.1 rees 168: break;
169: case 'f':
1.7 rees 170: rflags |= STRFORCE;
1.1 rees 171: break;
172: }
173: }
174:
175: if (fd < 0) {
1.3 rees 176: fd = sectok_open(port, oflags, &sw);
1.1 rees 177: if (fd < 0) {
1.3 rees 178: sectok_print_sw(sw);
1.1 rees 179: return -1;
180: }
181: }
182:
1.4 rees 183: aut0_vfyd = 0;
184:
1.7 rees 185: n = sectok_reset(fd, rflags, atr, &sw);
1.16 ! rees 186: if (vflag) {
! 187: #ifdef __palmos__
! 188: hidefield(printfield->id);
! 189: sectok_parse_atr(fd, STRV, atr, n, ¶m);
! 190: showfield(printfield->id);
! 191: #else
1.11 rees 192: sectok_parse_atr(fd, STRV, atr, n, ¶m);
1.16 ! rees 193: #endif
! 194: }
1.7 rees 195: if (!sectok_swOK(sw)) {
196: printf("sectok_reset: %s\n", sectok_get_sw(sw));
197: dclose(0, NULL);
1.1 rees 198: return -1;
199: }
200:
201: return 0;
202: }
203:
204: int dclose(int ac, char *av[])
205: {
206: if (fd >= 0) {
1.11 rees 207: sectok_close(fd);
1.1 rees 208: fd = -1;
209: }
210: return 0;
211: }
212:
213: int quit(int ac, char *av[])
214: {
1.15 rees 215: #ifndef __palmos__
1.1 rees 216: exit(0);
1.15 rees 217: #else
218: return -1;
219: #endif
1.1 rees 220: }
221:
222: int apdu(int ac, char *av[])
223: {
1.9 rees 224: int i, ilen, olen, n, ins, xcl = cla, p1, p2, p3, sw;
225: unsigned char ibuf[256], obuf[256], *bp;
1.1 rees 226:
227: optind = optreset = 1;
228:
229: while ((i = getopt(ac, av, "c:")) != -1) {
230: switch (i) {
231: case 'c':
232: sscanf(optarg, "%x", &xcl);
233: break;
234: }
235: }
236:
237: if (ac - optind < 4) {
1.4 rees 238: printf("usage: apdu [ -c class ] ins p1 p2 p3 data ...\n");
1.1 rees 239: return -1;
240: }
241:
242: sscanf(av[optind++], "%x", &ins);
243: sscanf(av[optind++], "%x", &p1);
244: sscanf(av[optind++], "%x", &p2);
245: sscanf(av[optind++], "%x", &p3);
246:
1.9 rees 247: for (bp = ibuf, i = optind, ilen = 0; i < ac; i++) {
1.1 rees 248: sscanf(av[i], "%x", &n);
249: *bp++ = n;
1.9 rees 250: ilen++;
1.1 rees 251: }
252:
1.7 rees 253: if (fd < 0 && reset(0, NULL) < 0)
254: return -1;
1.1 rees 255:
1.9 rees 256: olen = (p3 && !ilen) ? p3 : sizeof obuf;
1.1 rees 257:
1.9 rees 258: n = sectok_apdu(fd, xcl, ins, p1, p2, ilen, ibuf, olen, obuf, &sw);
1.1 rees 259:
1.9 rees 260: sectok_dump_reply(obuf, n, sw);
1.1 rees 261:
262: return 0;
263: }
264:
265: int selfid(int ac, char *av[])
266: {
1.12 rees 267: unsigned char fid[16], obuf[256];
268: char *fname;
1.16 ! rees 269: int i, n, sel, fidlen, vflag = 0, sw;
1.1 rees 270:
1.11 rees 271: optind = optreset = 1;
272:
273: while ((i = getopt(ac, av, "v")) != -1) {
274: switch (i) {
275: case 'v':
1.16 ! rees 276: vflag = 1;
1.11 rees 277: break;
278: }
279: }
280:
1.12 rees 281: if (ac - optind == 0) {
282: /* No fid/aid given; select null aid (default loader for Cyberflex) */
283: sel = 4;
284: fidlen = 0;
285: } else {
286: fname = av[optind++];
287: if (!strcmp(fname, "..")) {
288: /* Special case ".." means parent */
289: sel = 3;
290: fidlen = 0;
291: } else if (strlen(fname) < 5) {
292: /* fid */
293: sel = 0;
294: fidlen = 2;
295: sectok_parse_fname(fname, fid);
296: } else {
297: /* aid */
298: sel = 4;
299: fidlen = sectok_parse_input(fname, fid, sizeof fid);
1.13 rees 300: if (fname[0] == '#') {
301: /* Prepend 0xfc to the aid to make it a "proprietary aid". */
302: fid[0] = 0xfc;
303: }
1.12 rees 304: }
1.1 rees 305: }
306:
1.7 rees 307: if (fd < 0 && reset(0, NULL) < 0)
308: return -1;
1.1 rees 309:
1.16 ! rees 310: n = sectok_apdu(fd, cla, 0xa4, sel, 0, fidlen, fid, 256, obuf, &sw);
1.11 rees 311: if (!sectok_swOK(sw)) {
312: printf("Select %02x%02x: %s\n", fid[0], fid[1], sectok_get_sw(sw));
1.2 rees 313: return -1;
1.12 rees 314: }
315:
1.16 ! rees 316: if (vflag && !n && sectok_r1(sw) == 0x61 && sectok_r2(sw)) {
1.12 rees 317: /* The card has out data but we must explicitly ask for it */
318: n = sectok_apdu(fd, cla, 0xc0, 0, 0, 0, NULL, sectok_r2(sw), obuf, &sw);
1.2 rees 319: }
1.1 rees 320:
1.16 ! rees 321: if (n >= 4) {
! 322: /* Some cards put the file length here. No guarantees. */
! 323: curlen = (obuf[2] << 8) | obuf[3];
! 324: }
! 325:
! 326: if (vflag)
1.11 rees 327: sectok_dump_reply(obuf, n, sw);
328:
1.3 rees 329: return 0;
330: }
331:
332: int isearch(int ac, char *av[])
333: {
1.11 rees 334: int i, r1, sw;
1.3 rees 335:
1.7 rees 336: if (fd < 0 && reset(0, NULL) < 0)
337: return -1;
1.3 rees 338:
339: /* find instructions */
1.11 rees 340: for (i = 0; i < 0xff; i += 2) {
341: sectok_apdu(fd, cla, i, 0, 0, 0, NULL, 0, NULL, &sw);
342: r1 = sectok_r1(sw);
343: if (r1 != 0x06 && r1 != 0x6d && r1 != 0x6e)
344: printf("%02x %s %s\n", i, sectok_get_ins(i), sectok_get_sw(sw));
345: }
1.1 rees 346: return 0;
347: }
348:
349: int class(int ac, char *av[])
350: {
351: if (ac > 1)
352: sscanf(av[1], "%x", &cla);
353: else
354: printf("Class %02x\n", cla);
355: return 0;
356: }
357:
358: int dread(int ac, char *av[])
359: {
1.15 rees 360: int i, n, col = 0, fsize, xflag = 0, sw;
361: unsigned int p3;
362: unsigned char buf[CARDIOSIZE+1];
1.1 rees 363:
1.10 rees 364: optind = optreset = 1;
365:
366: while ((i = getopt(ac, av, "x")) != -1) {
367: switch (i) {
368: case 'x':
369: xflag = 1;
370: break;
371: }
372: }
373:
1.16 ! rees 374: if (ac - optind < 1)
! 375: fsize = curlen;
! 376: else
! 377: sscanf(av[optind++], "%d", &fsize);
! 378:
! 379: if (!fsize) {
! 380: printf("please specify filesize\n");
1.1 rees 381: return -1;
382: }
383:
1.7 rees 384: if (fd < 0 && reset(0, NULL) < 0)
385: return -1;
1.1 rees 386:
1.15 rees 387: for (p3 = 0; fsize && p3 < MAXFILELEN; p3 += n) {
1.1 rees 388: n = (fsize < CARDIOSIZE) ? fsize : CARDIOSIZE;
1.10 rees 389: n = sectok_apdu(fd, cla, 0xb0, p3 >> 8, p3 & 0xff, 0, NULL, n, buf, &sw);
390: if (!sectok_swOK(sw)) {
1.11 rees 391: printf("ReadBinary: %s\n", sectok_get_sw(sw));
1.1 rees 392: break;
393: }
1.16 ! rees 394: #ifdef __palmos__
1.10 rees 395: if (xflag) {
1.16 ! rees 396: hidefield(printfield->id);
1.10 rees 397: for (i = 0; i < n; i++) {
398: printf("%02x ", buf[i]);
1.16 ! rees 399: if (col++ % 12 == 11)
1.10 rees 400: printf("\n");
401: }
1.16 ! rees 402: showfield(printfield->id);
1.15 rees 403: } else {
404: buf[n] = '\0';
405: printf("%s", buf);
1.16 ! rees 406: }
1.15 rees 407: #else
1.16 ! rees 408: if (xflag) {
! 409: for (i = 0; i < n; i++) {
! 410: printf("%02x ", buf[i]);
! 411: if (col++ % 16 == 15)
! 412: printf("\n");
! 413: }
! 414: } else
1.10 rees 415: fwrite(buf, 1, n, stdout);
1.15 rees 416: #endif
1.1 rees 417: fsize -= n;
418: }
1.10 rees 419:
420: if (xflag && col % 16 != 0)
421: printf("\n");
1.1 rees 422:
423: return 0;
424: }
425:
1.15 rees 426: #ifndef __palmos__
1.1 rees 427: int dwrite(int ac, char *av[])
428: {
1.11 rees 429: int n, p3, sw;
1.1 rees 430: FILE *f;
431: unsigned char buf[CARDIOSIZE];
432:
433: if (ac != 2) {
434: printf("usage: write input-filename\n");
435: return -1;
436: }
437:
1.7 rees 438: if (fd < 0 && reset(0, NULL) < 0)
439: return -1;
1.1 rees 440:
441: f = fopen(av[1], "r");
442: if (!f) {
443: printf("can't open %s\n", av[1]);
444: return -1;
445: }
446:
447: n = 0;
448: while ((p3 = fread(buf, 1, CARDIOSIZE, f)) > 0) {
1.11 rees 449: sectok_apdu(fd, cla, 0xd6, n >> 8, n & 0xff, p3, buf, 0, NULL, &sw);
450: if (!sectok_swOK(sw)) {
451: printf("UpdateBinary: %s\n", sectok_get_sw(sw));
1.1 rees 452: break;
453: }
454: n += p3;
455: }
456: fclose(f);
457:
458: return (n ? 0 : -1);
459: }
1.16 ! rees 460: #else
! 461: int dwrite(int ac, char *av[])
! 462: {
! 463: int n, sw;
! 464: char *s;
! 465:
! 466: if (ac != 2) {
! 467: printf("usage: write text\n");
! 468: return -1;
! 469: }
! 470: s = av[1];
! 471: n = strlen(s);
! 472: sectok_apdu(fd, cla, 0xd6, 0, 0, n, s, 0, NULL, &sw);
! 473: if (!sectok_swOK(sw)) {
! 474: printf("UpdateBinary: %s\n", sectok_get_sw(sw));
! 475: return -1;
! 476: }
! 477: return 0;
! 478: }
1.15 rees 479: #endif
1.16 ! rees 480:
! 481: int challenge(int ac, char *av[])
! 482: {
! 483: int n = 8, sw;
! 484: unsigned char buf[256];
! 485:
! 486: if (ac > 1)
! 487: n = atoi(av[1]);
! 488:
! 489: n = sectok_apdu(fd, cla, 0x84, 0, 0, 0, NULL, n, buf, &sw);
! 490:
! 491: if (!sectok_swOK(sw)) {
! 492: printf("GetChallenge: %s\n", sectok_get_sw(sw));
! 493: return -1;
! 494: }
! 495:
! 496: sectok_dump_reply(buf, n, sw);
! 497: return 0;
! 498: }