1 /* $OpenBSD: skey.c,v 1.35 2019/01/25 00:19:26 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, &errstr); 64 if (errstr) 65 usage(); 66 break; 67 case 'p': 68 if (++i == argc) 69 usage(); 70 if (strlcpy(passwd, argv[i], sizeof(passwd)) >= 71 sizeof(passwd)) 72 errx(1, "Password too long"); 73 pass = 1; 74 break; 75 case 'x': 76 hexmode = 1; 77 break; 78 default: 79 usage(); 80 } 81 } else { 82 /* Multi character switches are hash types */ 83 if (skey_set_algorithm(&argv[i][1]) == NULL) { 84 warnx("Unknown hash algorithm %s", &argv[i][1]); 85 usage(); 86 } 87 } 88 i++; 89 } 90 91 if (argc > i + 2) 92 usage(); 93 94 /* Could be in the form <number>/<seed> */ 95 if (argc <= i + 1) { 96 /* look for / in it */ 97 if (argc <= i) 98 usage(); 99 slash = strchr(argv[i], '/'); 100 if (slash == NULL) 101 usage(); 102 *slash++ = '\0'; 103 seed = slash; 104 105 n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); 106 if (errstr) { 107 warnx("%s: %s", argv[i], errstr); 108 usage(); 109 } 110 } else { 111 n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); 112 if (errstr) { 113 warnx("%s: %s", argv[i], errstr); 114 usage(); 115 } 116 seed = argv[++i]; 117 } 118 119 /* Get user's secret passphrase */ 120 if (!pass && (readpassphrase("Enter secret passphrase: ", passwd, 121 sizeof(passwd), 0) == NULL || passwd[0] == '\0')) 122 exit(1); 123 124 /* Crunch seed and passphrase into starting key */ 125 if (keycrunch(key, seed, passwd) != 0) { 126 explicit_bzero(passwd, sizeof(passwd)); 127 errx(1, "key crunch failed"); 128 } 129 130 explicit_bzero(passwd, sizeof(passwd)); 131 132 if (cnt == 1) { 133 while (n-- != 0) 134 f(key); 135 (void)puts(hexmode ? put8(buf, key) : btoe(buf, key)); 136 } else { 137 for (i = 0; i <= n - cnt; i++) 138 f(key); 139 for (; i <= n; i++) { 140 if (hexmode) 141 (void)printf("%d: %s\n", i, put8(buf, key)); 142 else 143 (void)printf("%d: %-29s\n", i, btoe(buf, key)); 144 f(key); 145 } 146 } 147 exit(0); 148 } 149 150 void 151 usage(void) 152 { 153 fprintf(stderr, 154 "usage: %s [-x] [-md5 | -rmd160 | -sha1] [-n count]\n\t" 155 "[-p passphrase] <sequence#>[/] key\n", __progname); 156 exit(1); 157 } 158