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