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
main(int argc,char ** argv)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", 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
predict(DES_key_schedule ks,const char * chal,int cnt)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 }
201