1 |
|
|
/* $OpenBSD: x99token.c,v 1.13 2017/05/03 09:51:39 mestre Exp $ */ |
2 |
|
|
|
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> |
7 |
|
|
* |
8 |
|
|
* Donated to the Public Domain by Paul Borman |
9 |
|
|
*/ |
10 |
|
|
|
11 |
|
|
#include <sys/stat.h> |
12 |
|
|
|
13 |
|
|
#include <ctype.h> |
14 |
|
|
#include <err.h> |
15 |
|
|
#include <pwd.h> |
16 |
|
|
#include <readpassphrase.h> |
17 |
|
|
#include <stdio.h> |
18 |
|
|
#include <stdlib.h> |
19 |
|
|
#include <string.h> |
20 |
|
|
#include <unistd.h> |
21 |
|
|
#include <limits.h> |
22 |
|
|
#include <openssl/des.h> |
23 |
|
|
|
24 |
|
|
#define KEYFILE ".keyfile.des" |
25 |
|
|
#define HEXDIGITS "0123456789abcdef" |
26 |
|
|
#define DECDIGITS "0123456789012345" |
27 |
|
|
|
28 |
|
|
void predict(DES_key_schedule, const char *, int); |
29 |
|
|
|
30 |
|
|
char *digits = HEXDIGITS; |
31 |
|
|
extern char *__progname; |
32 |
|
|
|
33 |
|
|
int |
34 |
|
|
main(int argc, char **argv) |
35 |
|
|
{ |
36 |
|
|
int i; |
37 |
|
|
char buf[256]; |
38 |
|
|
DES_key_schedule ks; |
39 |
|
|
DES_cblock key; |
40 |
|
|
char _keyfile[PATH_MAX]; |
41 |
|
|
char *keyfile = 0; |
42 |
|
|
FILE *fp; |
43 |
|
|
int init = 0; |
44 |
|
|
int hex = 1; |
45 |
|
|
int cnt = 1; |
46 |
|
|
unsigned int pin; |
47 |
|
|
struct passwd *pwd; |
48 |
|
|
|
49 |
|
|
if (pledge("stdio rpath wpath cpath getpw tty flock", NULL) == -1) |
50 |
|
|
err(1, "pledge"); |
51 |
|
|
|
52 |
|
|
while ((i = getopt(argc, argv, "dk:in:")) != -1) { |
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); |
65 |
|
|
if (cnt <= 0) |
66 |
|
|
err(1, "invalid count: %s", optarg); |
67 |
|
|
break; |
68 |
|
|
default: |
69 |
|
|
fprintf(stderr, |
70 |
|
|
"usage: %s [-d] [-k keyfile] [-n count]\n" |
71 |
|
|
" %s -i [-k keyfile]\n", |
72 |
|
|
__progname, __progname); |
73 |
|
|
exit(1); |
74 |
|
|
} |
75 |
|
|
} |
76 |
|
|
|
77 |
|
|
if (!keyfile) { |
78 |
|
|
if ((pwd = getpwuid(getuid())) == NULL) { |
79 |
|
|
fprintf(stderr, "Say, just who are you, anyhow?\n"); |
80 |
|
|
exit(1); |
81 |
|
|
} |
82 |
|
|
snprintf(_keyfile, sizeof(_keyfile), "%s/%s", pwd->pw_dir, |
83 |
|
|
KEYFILE); |
84 |
|
|
keyfile = _keyfile; |
85 |
|
|
} |
86 |
|
|
|
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 { |
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) { |
104 |
|
|
if (!*b) |
105 |
|
|
fprintf(stderr, "%s: invalid key\n", buf); |
106 |
|
|
while (isdigit((unsigned char)*b)) |
107 |
|
|
key[i] = key[i] << 3 | (*b++ - '0'); |
108 |
|
|
while (*b && !isdigit((unsigned char)*b)) |
109 |
|
|
++b; |
110 |
|
|
} |
111 |
|
|
} else { |
112 |
|
|
for (i = 0; i < 16; ++i) { |
113 |
|
|
int d; |
114 |
|
|
|
115 |
|
|
if (islower((unsigned char)buf[i])) |
116 |
|
|
buf[i] = toupper((unsigned char)buf[i]); |
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 |
|
|
} |
127 |
|
|
} |
128 |
|
|
|
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) |
132 |
|
|
if (isdigit((unsigned char)buf[i])) |
133 |
|
|
pin = pin * 16 + buf[i] - '0' + 1; |
134 |
|
|
|
135 |
|
|
if ((pin & 0xffff0000) == 0) |
136 |
|
|
pin |= pin << 16; |
137 |
|
|
|
138 |
|
|
for (i = 0; i < 8; ++i) |
139 |
|
|
key[0] ^= (pin >> ((i * 7) % 26)) & 0x7f; |
140 |
|
|
|
141 |
|
|
if (init) { |
142 |
|
|
umask(S_IRWXG | S_IRWXO); |
143 |
|
|
unlink(keyfile); |
144 |
|
|
if ((fp = fopen(keyfile, "w")) == NULL) |
145 |
|
|
err(1, "could not open %s for writing", keyfile); |
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 |
|
|
} |
150 |
|
|
fputc('\n', fp); |
151 |
|
|
fclose(fp); |
152 |
|
|
exit(0); |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
DES_fixup_key_parity(&key); |
156 |
|
|
DES_key_sched(&key, &ks); |
157 |
|
|
|
158 |
|
|
buf[0] = '\0'; |
159 |
|
|
readpassphrase("Enter challenge: ", buf, sizeof(buf), RPP_ECHO_ON); |
160 |
|
|
if (buf[0] == '\0') |
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 |
|
|
|
172 |
|
|
explicit_bzero(&ks, sizeof(ks)); |
173 |
|
|
explicit_bzero(buf, sizeof(buf)); |
174 |
|
|
|
175 |
|
|
exit(0); |
176 |
|
|
} |
177 |
|
|
|
178 |
|
|
void |
179 |
|
|
predict(DES_key_schedule ks, const char *chal, int cnt) |
180 |
|
|
{ |
181 |
|
|
int i; |
182 |
|
|
DES_cblock cb; |
183 |
|
|
|
184 |
|
|
memcpy(&cb, chal, sizeof(cb)); |
185 |
|
|
while (cnt-- > 0) { |
186 |
|
|
printf("%.8s: ", (char *)cb); |
187 |
|
|
DES_ecb_encrypt(&cb, &cb, &ks, DES_ENCRYPT); |
188 |
|
|
for (i = 0; i < 4; ++i) { |
189 |
|
|
printf("%c", digits[(cb[i]>>4) & 0xf]); |
190 |
|
|
printf("%c", digits[(cb[i]>>0) & 0xf]); |
191 |
|
|
} |
192 |
|
|
putchar('\n'); |
193 |
|
|
for (i = 0; i < 8; ++i) { |
194 |
|
|
if ((cb[i] &= 0xf) > 9) |
195 |
|
|
cb[i] -= 10; |
196 |
|
|
cb[i] |= 0x30; |
197 |
|
|
} |
198 |
|
|
} |
199 |
|
|
memset(&cb, 0, sizeof(cb)); |
200 |
|
|
} |