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