summaryrefslogtreecommitdiffstats
path: root/contrib/telnet/libtelnet/pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/telnet/libtelnet/pk.c')
-rw-r--r--contrib/telnet/libtelnet/pk.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/contrib/telnet/libtelnet/pk.c b/contrib/telnet/libtelnet/pk.c
new file mode 100644
index 0000000..78e474f
--- /dev/null
+++ b/contrib/telnet/libtelnet/pk.c
@@ -0,0 +1,266 @@
+/* public key routines */
+/* functions:
+ genkeys(char *public, char *secret)
+ common_key(char *secret, char *public, desData *deskey)
+ pk_encode(char *in, *out, DesData *deskey);
+ pk_decode(char *in, *out, DesData *deskey);
+ where
+ char public[HEXKEYBYTES + 1];
+ char secret[HEXKEYBYTES + 1];
+ */
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <string.h>
+#include <fcntl.h>
+#include <des.h>
+#include "mp.h"
+#include "pk.h"
+#if defined(SOLARIS2) || defined(LINUX)
+#include <stdlib.h>
+#endif
+
+/*
+ * Choose top 128 bits of the common key to use as our idea key.
+ */
+static
+extractideakey(ck, ideakey)
+ MINT *ck;
+ IdeaData *ideakey;
+{
+ MINT *a;
+ MINT *z;
+ short r;
+ int i;
+ short base = (1 << 8);
+ char *k;
+
+ z = itom(0);
+ a = itom(0);
+ madd(ck, z, a);
+ for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
+ sdiv(a, base, a, &r);
+ }
+ k = (char *)ideakey;
+ for (i = 0; i < 16; i++) {
+ sdiv(a, base, a, &r);
+ *k++ = r;
+ }
+ mfree(z);
+ mfree(a);
+}
+
+/*
+ * Choose middle 64 bits of the common key to use as our des key, possibly
+ * overwriting the lower order bits by setting parity.
+ */
+static
+extractdeskey(ck, deskey)
+ MINT *ck;
+ DesData *deskey;
+{
+ MINT *a;
+ MINT *z;
+ short r;
+ int i;
+ short base = (1 << 8);
+ char *k;
+
+ z = itom(0);
+ a = itom(0);
+ madd(ck, z, a);
+ for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
+ sdiv(a, base, a, &r);
+ }
+ k = (char *)deskey;
+ for (i = 0; i < 8; i++) {
+ sdiv(a, base, a, &r);
+ *k++ = r;
+ }
+ mfree(z);
+ mfree(a);
+}
+
+/*
+ * get common key from my secret key and his public key
+ */
+void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
+{
+ MINT *public;
+ MINT *secret;
+ MINT *common;
+ MINT *modulus = xtom(HEXMODULUS);
+
+ public = xtom(xpublic);
+ secret = xtom(xsecret);
+ common = itom(0);
+ pow(public, secret, modulus, common);
+ extractdeskey(common, deskey);
+ extractideakey(common, ideakey);
+#if DES_OSTHOLM
+ des_fixup_key_parity(deskey);
+#else
+ des_set_odd_parity(deskey);
+#endif
+ mfree(common);
+ mfree(secret);
+ mfree(public);
+ mfree(modulus);
+}
+
+
+/*
+ * Generate a seed
+ */
+void getseed(seed, seedsize)
+ char *seed;
+ int seedsize;
+{
+ int i,f;
+ int rseed;
+ struct timeval tv;
+ long devrand;
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ rseed = tv.tv_sec + tv.tv_usec;
+/* XXX What the hell is this?! */
+ for (i = 0; i < 8; i++) {
+ rseed ^= (rseed << 8);
+ }
+
+ f=open("/dev/random",O_NONBLOCK|O_RDONLY);
+ if (f>=0)
+ {
+ read(f,&devrand,sizeof(devrand));
+ close(f);
+ }
+ srand48((long)rseed^devrand);
+
+ for (i = 0; i < seedsize; i++) {
+ seed[i] = (lrand48() & 0xff);
+ }
+}
+
+
+/*
+ * Generate a random public/secret key pair
+ */
+void genkeys(public, secret)
+ char *public;
+ char *secret;
+{
+ int i;
+
+# define BASEBITS (8*sizeof(short) - 1)
+# define BASE (1 << BASEBITS)
+
+ MINT *pk = itom(0);
+ MINT *sk = itom(0);
+ MINT *tmp;
+ MINT *base = itom(BASE);
+ MINT *root = itom(PROOT);
+ MINT *modulus = xtom(HEXMODULUS);
+ short r;
+ unsigned short seed[KEYSIZE/BASEBITS + 1];
+ char *xkey;
+
+ getseed((char *)seed, sizeof(seed));
+ for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
+ r = seed[i] % BASE;
+ tmp = itom(r);
+ mult(sk, base, sk);
+ madd(sk, tmp, sk);
+ mfree(tmp);
+ }
+ tmp = itom(0);
+ mdiv(sk, modulus, tmp, sk);
+ mfree(tmp);
+ pow(root, sk, modulus, pk);
+ xkey = mtox(sk);
+ adjust(secret, xkey);
+ xkey = mtox(pk);
+ adjust(public, xkey);
+ mfree(sk);
+ mfree(base);
+ mfree(pk);
+ mfree(root);
+ mfree(modulus);
+}
+
+/*
+ * Adjust the input key so that it is 0-filled on the left
+ */
+adjust(keyout, keyin)
+ char keyout[HEXKEYBYTES+1];
+ char *keyin;
+{
+ char *p;
+ char *s;
+
+ for (p = keyin; *p; p++)
+ ;
+ for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
+ *s = *p;
+ }
+ while (s >= keyout) {
+ *s-- = '0';
+ }
+}
+
+static char hextab[17] = "0123456789ABCDEF";
+
+/* given a DES key, cbc encrypt and translate input to terminated hex */
+void pk_encode(in, out, key)
+char *in,*out;
+DesData *key;
+{
+ char buf[256];
+ DesData i;
+ des_key_schedule k;
+ int l,op,deslen;
+
+ memset(&i,0,sizeof(i));
+ memset(buf,0,sizeof(buf));
+ deslen = ((strlen(in) + 7)/8)*8;
+ des_key_sched(key, k);
+ des_cbc_encrypt((des_cblock *)in,(des_cblock *)buf,deslen,
+ k,&i,DES_ENCRYPT);
+ for (l=0,op=0;l<deslen;l++) {
+ out[op++] = hextab[(buf[l] & 0xf0) >> 4];
+ out[op++] = hextab[(buf[l] & 0x0f)];
+ }
+ out[op] = '\0';
+}
+
+/* given a DES key, translate input from hex and decrypt */
+void pk_decode(in, out, key)
+char *in,*out;
+DesData *key;
+{
+ char buf[256];
+ DesData i;
+ des_key_schedule k;
+ int l,n1,n2,op;
+
+ memset(&i,0,sizeof(i));
+ memset(buf,0,sizeof(buf));
+ for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
+ if(in[op] == '0' && in[op+1] == '0') {
+ buf[l] = '\0';
+ break;
+ }
+ if (in[op] > '9')
+ n1 = in[op] - 'A' + 10;
+ else
+ n1 = in[op] - '0';
+ if (in[op+1] > '9')
+ n2 = in[op+1] - 'A' + 10;
+ else
+ n2 = in[op+1] - '0';
+ buf[l] = n1*16 +n2;
+ }
+ des_key_sched(key, k);
+ des_cbc_encrypt((des_cblock *)buf,(des_cblock *)out,strlen(in)/2,
+ k,&i,DES_DECRYPT);
+ out[strlen(in)/2] = '\0';
+}
OpenPOWER on IntegriCloud