xref: /openbsd-src/usr.bin/skey/skey.c (revision 8e0d42cd5717ce2a9fdca7fbc0f490680a91ef37)
1 /*	$OpenBSD: skey.c,v 1.36 2024/08/03 22:00:31 millert Exp $	*/
2 /*
3  * OpenBSD S/Key (skey.c)
4  *
5  * Authors:
6  *          Neil M. Haller <nmh@thumper.bellcore.com>
7  *          Philip R. Karn <karn@chicago.qualcomm.com>
8  *          John S. Walden <jsw@thumper.bellcore.com>
9  *          Scott Chasin <chasin@crimelab.com>
10  *          Todd C. Miller <millert@openbsd.org>
11  *
12  *
13  * Stand-alone program for computing responses to S/Key challenges.
14  * Takes the iteration count and seed as command line args, prompts
15  * for the user's key, and produces both word and hex format responses.
16  *
17  * Usage example:
18  *	>skey 88 ka9q2
19  *	Enter password:
20  *	OMEN US HORN OMIT BACK AHOY
21  *	>
22  *
23  */
24 
25 #include <err.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <readpassphrase.h>
32 #include <skey.h>
33 
34 void usage();
35 
36 extern char *__progname;
37 
38 int
39 main(int argc, char *argv[])
40 {
41 	int     n, i, cnt = 1, pass = 0, hexmode = 0;
42 	char    passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE];
43 	char	buf[33], *seed, *slash, *algo;
44 	const char *errstr;
45 
46 	if (pledge("stdio tty", NULL) == -1)
47 		err(1, "pledge");
48 
49 	/* If we were called as otp-METHOD, set algorithm based on that */
50 	if (strncmp(__progname, "otp-", 4) == 0) {
51 		algo = __progname + 4;
52 		if (skey_set_algorithm(algo) == NULL)
53 			errx(1, "Unknown hash algorithm %s", algo);
54 	}
55 
56 	for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) {
57 		if (argv[i][2] == '\0') {
58 			/* Single character switch */
59 			switch (argv[i][1]) {
60 			case 'n':
61 				if (++i == argc)
62 					usage();
63 				cnt = strtonum(argv[i], 1, SKEY_MAX_SEQ + 1,
64 				    &errstr);
65 				if (errstr)
66 					usage();
67 				break;
68 			case 'p':
69 				if (++i == argc)
70 					usage();
71 				if (strlcpy(passwd, argv[i], sizeof(passwd)) >=
72 				    sizeof(passwd))
73 					errx(1, "Password too long");
74 				pass = 1;
75 				break;
76 			case 'x':
77 				hexmode = 1;
78 				break;
79 			default:
80 				usage();
81 			}
82 		} else {
83 			/* Multi character switches are hash types */
84 			if (skey_set_algorithm(&argv[i][1]) == NULL) {
85 				warnx("Unknown hash algorithm %s", &argv[i][1]);
86 				usage();
87 			}
88 		}
89 		i++;
90 	}
91 
92 	if (argc > i + 2)
93 		usage();
94 
95 	/* Could be in the form <number>/<seed> */
96 	if (argc <= i + 1) {
97 		/* look for / in it */
98 		if (argc <= i)
99 			usage();
100 		slash = strchr(argv[i], '/');
101 		if (slash == NULL)
102 			usage();
103 		*slash++ = '\0';
104 		seed = slash;
105 
106 		n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr);
107 		if (errstr) {
108 			warnx("%s: %s", argv[i], errstr);
109 			usage();
110 		}
111 	} else {
112 		n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr);
113 		if (errstr) {
114 			warnx("%s: %s", argv[i], errstr);
115 			usage();
116 		}
117 		seed = argv[++i];
118 	}
119 
120 	/* Get user's secret passphrase */
121 	if (!pass && (readpassphrase("Enter secret passphrase: ", passwd,
122 	    sizeof(passwd), 0) == NULL || passwd[0] == '\0'))
123 		exit(1);
124 
125 	/* Crunch seed and passphrase into starting key */
126 	if (keycrunch(key, seed, passwd) != 0) {
127 		explicit_bzero(passwd, sizeof(passwd));
128 		errx(1, "key crunch failed");
129 	}
130 
131 	explicit_bzero(passwd, sizeof(passwd));
132 
133 	if (cnt == 1) {
134 		while (n-- != 0)
135 			f(key);
136 		(void)puts(hexmode ? put8(buf, key) : btoe(buf, key));
137 	} else {
138 		for (i = 0; i <= n - cnt; i++)
139 			f(key);
140 		for (; i <= n; i++) {
141 			if (hexmode)
142 				(void)printf("%d: %s\n", i, put8(buf, key));
143 			else
144 				(void)printf("%d: %-29s\n", i, btoe(buf, key));
145 			f(key);
146 		}
147 	}
148 	exit(0);
149 }
150 
151 void
152 usage(void)
153 {
154 	fprintf(stderr,
155 	    "usage: %s [-x] [-md5 | -rmd160 | -sha1] [-n count]\n\t"
156 	    "[-p passphrase] <sequence#>[/] key\n", __progname);
157 	exit(1);
158 }
159