summaryrefslogtreecommitdiff
path: root/usr.bin/x99token
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2001-08-01 21:22:17 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2001-08-01 21:22:17 +0000
commit1ac2aed0bc10c864b69bfc6cb863a13891655ea1 (patch)
tree3726e0151afe9a2d04fad5f661caa55f41f354a5 /usr.bin/x99token
parent8d5861d3d12c5b3d729173dc07ede0df177a22ee (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/Makefile8
-rw-r--r--usr.bin/x99token/x99token.184
-rw-r--r--usr.bin/x99token/x99token.c244
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;
+ }
+ }
+}