Annotation of src/usr.bin/x99token/x99token.c, Revision 1.5
1.1 millert 1: /*
2: * X9.9 calculator
3: * This software is provided AS IS with no express or implied warranty
4: * October 1995, Paul Borman <prb@krystal.com>
1.5 ! millert 5: *
! 6: * Donated to the Public Domain by Paul Borman
1.1 millert 7: */
1.2 millert 8: #include <sys/param.h>
9: #include <sys/stat.h>
10:
11: #include <ctype.h>
12: #include <err.h>
1.1 millert 13: #include <pwd.h>
1.2 millert 14: #include <readpassphrase.h>
1.1 millert 15: #include <stdio.h>
16: #include <stdlib.h>
17: #include <string.h>
18: #include <unistd.h>
1.2 millert 19: #include <des.h>
1.1 millert 20:
1.2 millert 21: #define KEYFILE ".keyfile.des"
1.1 millert 22: #define HEXDIGITS "0123456789abcdef"
23: #define DECDIGITS "0123456789012345"
24:
1.4 millert 25: void predict(des_key_schedule, const char *, int);
1.2 millert 26:
1.1 millert 27: char *digits = HEXDIGITS;
1.2 millert 28: extern char *__progname;
1.1 millert 29:
30: int
1.2 millert 31: main(int argc, char **argv)
1.1 millert 32: {
33: int i;
34: char buf[256];
1.2 millert 35: des_key_schedule ks;
36: des_cblock key;
37: char _keyfile[MAXPATHLEN];
1.1 millert 38: char *keyfile = 0;
39: FILE *fp;
40: int init = 0;
41: int hex = 1;
42: int cnt = 1;
1.2 millert 43: unsigned int pin;
1.1 millert 44: struct passwd *pwd;
45:
1.2 millert 46: while ((i = getopt(argc, argv, "dk:in:")) != -1) {
1.1 millert 47: switch (i) {
48: case 'k':
49: keyfile = optarg;
50: break;
51: case 'i':
52: init = 1;
53: break;
54: case 'd':
55: hex = 0;
56: break;
57: case 'n':
58: cnt = atoi(optarg);
1.2 millert 59: if (cnt <= 0)
60: err(1, "invalid count: %s", optarg);
1.1 millert 61: break;
62: default:
1.2 millert 63: fprintf(stderr, "usage: %s [-n cnt] [-h] [-k keyfile]\n"
64: " %s -i [-k keyfile]\n", __progname,
65: __progname);
1.1 millert 66: exit(1);
67: }
1.2 millert 68: }
1.1 millert 69:
70: if (!keyfile) {
1.2 millert 71: if ((pwd = getpwuid(getuid())) == NULL) {
1.1 millert 72: fprintf(stderr, "Say, just who are you, anyhow?\n");
73: exit(1);
74: }
1.2 millert 75: snprintf(_keyfile, sizeof(_keyfile), "%s/%s", pwd->pw_dir,
76: KEYFILE);
1.1 millert 77: keyfile = _keyfile;
78: }
79:
1.2 millert 80: if (init)
81: readpassphrase("Enter Key: ", buf, sizeof(buf), 0);
82: else if ((fp = fopen(keyfile, "r")) == NULL)
83: err(1, "unable to open %s", keyfile);
84: else {
1.1 millert 85: if (fgets(buf, sizeof(buf), fp) == NULL) {
86: fprintf(stderr, "No key in %s\n", keyfile);
87: exit(1);
88: }
89: fclose(fp);
90: }
91:
92: memset(key, 0, sizeof(key));
93: if (init && buf[3] == ' ') {
94: char *b = buf;
95: /* Assume octal input */
96: for (i = 0; i < 8; ++i) {
1.4 millert 97: if (!*b)
1.1 millert 98: fprintf(stderr, "%s: invalid key\n", buf);
99: while (isdigit(*b))
1.4 millert 100: key[i] = key[i] << 3 | (*b++ - '0');
1.1 millert 101: while (*b && !isdigit(*b))
102: ++b;
103: }
1.2 millert 104: } else {
1.1 millert 105: for (i = 0; i < 16; ++i) {
106: int d;
107:
108: if (islower(buf[i]))
109: buf[i] = toupper(buf[i]);
110: if (buf[i] >= '0' && buf[i] <= '9')
111: d = buf[i] - '0';
112: else if (buf[i] >= 'A' && buf[i] <= 'F')
113: d = buf[i] - 'A' + 10;
114: else {
115: fprintf(stderr, "invalid key: %s\n", buf);
116: exit(1);
117: }
118: key[i>>1] |= d << ((i & 1) ? 0 : 4);
119: }
1.2 millert 120: }
1.1 millert 121:
1.2 millert 122: /* XXX - should warn on non-space or non-digit */
123: readpassphrase("Enter Pin: ", buf, sizeof(buf), 0);
124: for (i = 0, pin = 0; buf[i] && buf[i] != '\n'; ++i)
1.1 millert 125: if (isdigit(buf[i]))
126: pin = pin * 16 + buf[i] - '0' + 1;
127:
1.2 millert 128: if ((pin & 0xffff0000) == 0)
1.1 millert 129: pin |= pin << 16;
130:
131: for (i = 0; i < 8; ++i)
132: key[0] ^= (pin >> ((i * 7) % 26)) & 0x7f;
133:
134: if (init) {
1.2 millert 135: if ((fp = fopen(keyfile, "w")) == NULL)
136: err(1, "could not open %s for writing", keyfile);
137: fchmod(fileno(fp), 0600);
1.1 millert 138: for (i = 0; i < 8; ++i) {
139: fprintf(fp, "%c", digits[(key[i]>>4)&0xf]);
140: fprintf(fp, "%c", digits[(key[i]>>0)&0xf]);
141: }
1.2 millert 142: fputc('\n', fp);
1.1 millert 143: fclose(fp);
144: exit(0);
145: }
146:
1.2 millert 147: des_fixup_key_parity(&key);
148: des_key_sched(&key, ks);
1.1 millert 149:
1.2 millert 150: buf[0] = '\0';
1.3 deraadt 151: readpassphrase("Enter challenge: ", buf, sizeof(buf), RPP_ECHO_ON);
1.2 millert 152: if (buf[0] == '\0')
1.1 millert 153: exit(0);
154:
155: for (i = 0; i < 8; ++i)
156: if (buf[i] == '\n')
157: buf[i] = '\0';
158:
159: if (!hex)
160: digits = DECDIGITS;
161:
162: predict(ks, buf, cnt);
163:
1.2 millert 164: memset(&ks, 0, sizeof(ks));
165: memset(buf, 0, sizeof(buf));
166:
1.1 millert 167: exit(0);
168: }
169:
170: void
1.4 millert 171: predict(des_key_schedule ks, const char *chal, int cnt)
1.1 millert 172: {
173: int i;
1.2 millert 174: des_cblock cb;
1.1 millert 175:
1.4 millert 176: memcpy(&cb, chal, sizeof(cb));
1.1 millert 177: while (cnt-- > 0) {
1.4 millert 178: printf("%.8s: ", (char *)cb);
179: des_ecb_encrypt(&cb, &cb, ks, DES_ENCRYPT);
1.1 millert 180: for (i = 0; i < 4; ++i) {
1.2 millert 181: printf("%c", digits[(cb[i]>>4) & 0xf]);
182: printf("%c", digits[(cb[i]>>0) & 0xf]);
1.1 millert 183: }
1.2 millert 184: putchar('\n');
1.1 millert 185: for (i = 0; i < 8; ++i) {
1.2 millert 186: if ((cb[i] &= 0xf) > 9)
187: cb[i] -= 10;
188: cb[i] |= 0x30;
1.1 millert 189: }
190: }
1.2 millert 191: memset(&cb, 0, sizeof(cb));
1.1 millert 192: }