diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-08-01 21:22:17 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-08-01 21:22:17 +0000 |
commit | 1ac2aed0bc10c864b69bfc6cb863a13891655ea1 (patch) | |
tree | 3726e0151afe9a2d04fad5f661caa55f41f354a5 /usr.bin/x99token | |
parent | 8d5861d3d12c5b3d729173dc07ede0df177a22ee (diff) |
x99token, a software x99 token calculator from Paul Borman that can
be used with login_token and friends.
Diffstat (limited to 'usr.bin/x99token')
-rw-r--r-- | usr.bin/x99token/Makefile | 8 | ||||
-rw-r--r-- | usr.bin/x99token/x99token.1 | 84 | ||||
-rw-r--r-- | usr.bin/x99token/x99token.c | 244 |
3 files changed, 336 insertions, 0 deletions
diff --git a/usr.bin/x99token/Makefile b/usr.bin/x99token/Makefile new file mode 100644 index 00000000000..563a07c8973 --- /dev/null +++ b/usr.bin/x99token/Makefile @@ -0,0 +1,8 @@ +# BSDI $Id: Makefile,v 1.1 2001/08/01 21:22:16 millert Exp $ + +PROG= x99token +SRCS= x99token.c +CFLAGS+=-DKRBDES +LDADD+= -ldes + +.include <bsd.prog.mk> diff --git a/usr.bin/x99token/x99token.1 b/usr.bin/x99token/x99token.1 new file mode 100644 index 00000000000..90dab3a20ba --- /dev/null +++ b/usr.bin/x99token/x99token.1 @@ -0,0 +1,84 @@ +.TH X99TOKEN 1 "5 October 1995" +.SH NAME +x99token - X9.9 software token calculator +.SH SYNOPSIS +.PP +.B x99token [-d] [-i] [-k keyfile] [-n count] +.SH DESCRIPTION +The +.B x99token +program is a simple X9.9 software token calculator. +The token is initialized by using the +.B -i +option. +In this mode, +.B x99token +requests a key. The key consists of 8 bytes encoded in either hex +or octal. When encoded in hex the key must consist of 16 hex digits, +no spaces (e.g., "0123456789abcdef"). +When encoded in octal the key must consist of 8 3 digit +octets, each separated by exactly one space +(e.g., "001 010 100 002 020 200 003 030"). +Once the key is entered, a PIN number is requested. The PIN number is +used to perturb the key before it is stored in a keyfile. This perturbation +is not terribly secure. You should assume that anyone with access to your +keyfile will also have access to your key. +.PP +When +.B -i +is not specified, +.B x99token +is in calculator mode. +In this mode you must enter the same PIN as used above in the initialization +step. The PIN is used decode the the key read from the keyfile. +Next you enter the challenge you have been presented. +The +.B x99token +program will provide you a response to the challenge. If the +.B -d +option is used, the response will fold any hex digits to decimal. +If a +.I count +is specified by +.B -n , +it indicates the number of challenges to predict. The first challenge +is always the entered challenge. By default the value of +.I count +is 1, which implies only the entered challenge is resolved. +.PP +Future challenges are predicted by the following algorithm: +.nf +.sp +* Encrypt the current challenge with the shared secret key + +* AND each byte of the response with 0x0f + +* Modulo each byte by 10 (0x0a) + +* ADD 0x30 (ASCII value of '0') to each byte +.fi +.sp +The resulting 8 bytes are all ASCII decimal digits and are the +predicted challenge. This process may be repeated. +.SH FILES +.ta 3i +$HOME/.keyfile.des default keyfile under BSD +.br +keyfile.des default keyfle under DOS +.SH NOTES +This is a very simple minded program. It is recommended that the +keyfile be placed on a floppy disk which you keep physically secure. +Under DOS the keyfile is marked as both a hidden and system file. +When used with BSD/OS 3.0 or beyond, the token authentication type +supplies the appropriate challenges and initialization information. +.PP +Having not read the X9.9 standard, this may not be complete or accurate +implementation of that standard. This software is provided AS IS +with no express or implied warranty. +.SH AUTHOR +Paul Borman <prb@krystal.com> +.SH CREDITS +This code uses the publicly available des library written by Phil Karn, KA9Q. +The decryption code from Phil's library has been removed to allow +.B x99token +to be free of export restrictions (as it can only encrypt and not decrypt). diff --git a/usr.bin/x99token/x99token.c b/usr.bin/x99token/x99token.c new file mode 100644 index 00000000000..ed205909366 --- /dev/null +++ b/usr.bin/x99token/x99token.c @@ -0,0 +1,244 @@ +/* + * X9.9 calculator + * This software is provided AS IS with no express or implied warranty + * October 1995, Paul Borman <prb@krystal.com> + */ +#if defined(KRBDES) && !defined(__unix__) +#define __unix__ +#endif +#ifdef __unix__ +#ifdef LITTLE_ENDIAN +#undef LITTLE_ENDIAN +#endif +#include <pwd.h> +#else +#include <dos.h> +#endif +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +extern char *optarg; + + +#ifdef __unix__ +#define KEYFILE ".keyfile.des" +#define MPL 1024 +#else +#define KEYFILE "keyfile.des" +#define MPL 256 +#endif + +#define HEXDIGITS "0123456789abcdef" +#define DECDIGITS "0123456789012345" + +char *digits = HEXDIGITS; + +#ifdef KRBDES +#include <des.h> +#define setkey dessetkey + +void desinit(int i) { ; } +void dessetkey(char ks[16][8], char key[8]) +{ + des_key_schedule *k = (des_key_schedule *)ks; + des_fixup_key_parity((des_cblock *)key); + des_key_sched((des_cblock *)key, *k); +} +void endes(char ks[16][8], char key[8]) +{ + des_cblock cb; + des_key_schedule *k = (des_key_schedule *)ks; + + des_ecb_encrypt((des_cblock *)key, &cb, *k, DES_ENCRYPT); + memcpy(key, &cb, 8); +} +#endif + +void predict(char ks[16][8], char *chal, int cnt); + +int +main(int ac, char **av) +{ + int i; + char ks[16][8]; + char buf[256]; + char key[8]; + char _keyfile[MPL]; + char *keyfile = 0; + FILE *fp; + int init = 0; + int hex = 1; + int cnt = 1; + unsigned long pin; +#ifdef __unix__ + struct passwd *pwd; +#endif + + while ((i = getopt(ac, av, "dk:in:")) != EOF) + switch (i) { + case 'k': + keyfile = optarg; + break; + case 'i': + init = 1; + break; + case 'd': + hex = 0; + break; + case 'n': + cnt = atoi(optarg); + if (cnt <= 0) { + fprintf(stderr, "%s: invalid count\n", optarg); + exit(1); + } + break; + default: + fprintf(stderr, "Usage: x99token [-n cnt] [-h] [-k keyfile]\n" + " x99token -i [-k keyfile]\n"); + exit(1); + } + + desinit(0); + + if (!keyfile) { +#ifdef __unix__ + if ((pwd = getpwuid(getuid())) == 0) { + fprintf(stderr, "Say, just who are you, anyhow?\n"); + exit(1); + } + sprintf(_keyfile, "%s/%s", pwd->pw_dir, KEYFILE); + keyfile = _keyfile; +#else + keyfile = KEYFILE; +#endif + } + + if (init) { +#ifdef __unix__ + strcpy(buf, (char *)getpass("Enter Key: ")); +#else + printf("Enter key: "); + if (fgets(buf, sizeof(buf), stdin) == NULL) + exit(0); +#endif + } else if ((fp = fopen(keyfile, "r")) == NULL) { + fprintf(stderr, "Failed to open %s\n", keyfile); + exit(1); + } else { + if (fgets(buf, sizeof(buf), fp) == NULL) { + fprintf(stderr, "No key in %s\n", keyfile); + exit(1); + } + fclose(fp); + } + + memset(key, 0, sizeof(key)); + if (init && buf[3] == ' ') { + char *b = buf; + /* Assume octal input */ + for (i = 0; i < 8; ++i) { + if (!*b) { + fprintf(stderr, "%s: invalid key\n", buf); + } + while (isdigit(*b)) + key[i] = key[i] << 3 | *b++ - '0'; + while (*b && !isdigit(*b)) + ++b; + } + } else + for (i = 0; i < 16; ++i) { + int d; + + if (islower(buf[i])) + buf[i] = toupper(buf[i]); + if (buf[i] >= '0' && buf[i] <= '9') + d = buf[i] - '0'; + else if (buf[i] >= 'A' && buf[i] <= 'F') + d = buf[i] - 'A' + 10; + else { + fprintf(stderr, "invalid key: %s\n", buf); + exit(1); + } + key[i>>1] |= d << ((i & 1) ? 0 : 4); + } + +#ifdef __unix__ + strcpy(buf, (char *)getpass("Enter Pin: ")); +#else + printf("Enter Pin: "); + if (fgets(buf, sizeof(buf), stdin) == NULL) + exit(0); +#endif + + for (i = 0; buf[i] && buf[i] != '\n'; ++i) + if (isdigit(buf[i])) + pin = pin * 16 + buf[i] - '0' + 1; + + if ((pin & 0xffff0000L) == 0) + pin |= pin << 16; + + for (i = 0; i < 8; ++i) + key[0] ^= (pin >> ((i * 7) % 26)) & 0x7f; + + if (init) { + if ((fp = fopen(keyfile, "w")) == NULL) { + fprintf(stderr, "could not open %s for writing\n", + keyfile); + exit(1); + } + for (i = 0; i < 8; ++i) { + fprintf(fp, "%c", digits[(key[i]>>4)&0xf]); + fprintf(fp, "%c", digits[(key[i]>>0)&0xf]); + } + fprintf(fp, "\n"); + fclose(fp); +#ifdef __unix__ + chmod(keyfile, 0600); +#else + dos_setfileattr(keyfile, FA_HIDDEN | FA_SYSTEM); +#endif + exit(0); + } + + setkey(ks, key); + + printf("Enter challange: "); + memset(buf, 0, sizeof(buf)); + if (fgets(buf, sizeof(buf), stdin) == NULL) + exit(0); + + for (i = 0; i < 8; ++i) + if (buf[i] == '\n') + buf[i] = '\0'; + + if (!hex) + digits = DECDIGITS; + + predict(ks, buf, cnt); + + exit(0); +} + +void +predict(char ks[16][8], char *chal, int cnt) +{ + int i; + + while (cnt-- > 0) { + printf("%.8s: ", chal); + endes(ks, chal); + for (i = 0; i < 4; ++i) { + printf("%c", digits[(chal[i]>>4) & 0xf]); + printf("%c", digits[(chal[i]>>0) & 0xf]); + } + printf("\n"); + for (i = 0; i < 8; ++i) { + if ((chal[i] &= 0xf) > 9) + chal[i] -= 10; + chal[i] |= 0x30; + } + } +} |