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