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