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