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