WvStreams
wvdiffiehellman.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  * Copyright (C) 2003 Net Integration Technologies, Inc.
00004  *
00005  * Diffie-Hellman shared secret handshake.
00006  */
00007 
00008 #include "wvautoconf.h"
00009 #ifdef __GNUC__
00010 # define alloca __builtin_alloca
00011 #else
00012 # ifdef _MSC_VER
00013 #  include <malloc.h>
00014 #  define alloca _alloca
00015 # else
00016 #  if HAVE_ALLOCA_H
00017 #   include <alloca.h>
00018 #  else
00019 #   ifdef _AIX
00020 #pragma alloca
00021 #   else
00022 #    ifndef alloca /* predefined by HP cc +Olibcalls */
00023 char *alloca ();
00024 #    endif
00025 #   endif
00026 #  endif
00027 # endif
00028 #endif
00029 
00030 #include <openssl/bn.h>
00031 #include <stdlib.h>
00032 
00033 #include "wvdiffiehellman.h"
00034 #include "strutils.h"
00035 
00036 WvDiffieHellman::WvDiffieHellman(const unsigned char *_key, int _keylen, 
00037                                  BN_ULONG _generator) :
00038     generator(_generator), log("Diffie-Hellman", WvLog::Debug)
00039 {
00040     int problems;
00041     int check;
00042     {
00043         info = DH_new();
00044         info->p = BN_bin2bn(_key, _keylen, NULL);
00045 //      info->p->top = 0;
00046 //      info->p->dmax = _keylen * 8 / BN_BITS2;
00047 //      info->p->neg = 0;
00048 //      info->p->flags = 0;
00049 
00050         info->g = BN_new();
00051         BN_set_word(info->g, generator);
00052 //      info->g->d = &generator;
00053 //      info->g->top = 0;
00054 //      info->g->dmax = 1;
00055 //      info->g->neg = 0;
00056 //      info->g->flags = 0;
00057     }
00058 
00059     check = BN_mod_word(info->p, 24);
00060     DH_check(info, &problems);
00061     if (problems & DH_CHECK_P_NOT_PRIME)
00062         log(WvLog::Error, "Using a composite number for authentication.\n");
00063     if (problems & DH_CHECK_P_NOT_SAFE_PRIME)
00064         log(WvLog::Error,"Using an unsafe prime number for authentication.\n");
00065     if (problems & DH_NOT_SUITABLE_GENERATOR)
00066         log(WvLog::Error, "Can you just use 2 instead of %s (%s)!!\n",
00067             BN_bn2hex(info->g), check);
00068     if (problems & DH_UNABLE_TO_CHECK_GENERATOR)
00069         log(WvLog::Notice, "Using a strange argument for diffie-hellman.\n");
00070     DH_generate_key(info);
00071 }
00072 
00073 int WvDiffieHellman::pub_key_len()
00074 {
00075     return BN_num_bytes(info->pub_key);
00076 }
00077 
00078 int WvDiffieHellman::get_public_value(WvBuf &outbuf, int len)
00079 {
00080     int key_len = BN_num_bytes(info->pub_key);
00081     if (key_len < len)
00082         len = key_len;
00083 
00084     // alloca is stack allocated, don't free it.
00085     unsigned char *foo = (unsigned char*)alloca(key_len);
00086     BN_bn2bin(info->pub_key, foo);
00087     outbuf.put(foo, len);
00088 
00089     return len;
00090 }
00091 
00092 bool WvDiffieHellman::create_secret(WvBuf &inbuf, size_t in_len, WvBuf& outbuf)
00093 {
00094     unsigned char *foo = (unsigned char *)alloca(DH_size(info));
00095    log("My public value\n%s\nYour public value\n%s\n",BN_bn2hex(info->pub_key),
00096        hexdump_buffer(inbuf.peek(0, in_len), in_len, false));
00097     int len = DH_compute_key (foo, BN_bin2bn(inbuf.get(in_len), in_len, NULL), 
00098                               info);
00099 
00100     outbuf.put(foo, len);
00101 
00102     log("Shared secret\n%s\n",hexdump_buffer(outbuf.peek(0, len), len, false));
00103 
00104     return true;
00105 }