WvStreams
|
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 }