GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/x99token/x99token.c Lines: 0 100 0.0 %
Date: 2017-11-07 Branches: 0 81 0.0 %

Line Branch Exec Source
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
}