WvStreams
wvdsa.cc
00001 /*
00002  * Worldvisions Tunnel Vision Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * DSA cryptography abstractions.
00006  */
00007 #include <assert.h>
00008 #include <openssl/dsa.h>
00009 #include <openssl/pem.h>
00010 #include "wvsslhacks.h"
00011 #include "wvdsa.h"
00012 #include "wvhex.h"
00013 
00014 /***** WvDSAKey *****/
00015 
00016 WvDSAKey::WvDSAKey(const WvDSAKey &k)
00017 {
00018     if (k.prv)
00019         init(k.private_str(), true);
00020     else
00021         init(k.public_str(), false);
00022 }
00023 
00024 
00025 WvDSAKey::WvDSAKey(struct dsa_st *_dsa, bool priv)
00026 {
00027     if (_dsa == NULL)
00028     {
00029         // assert(_dsa);
00030         pub = WvString::null;
00031         prv = WvString::null;
00032         dsa = NULL;
00033         seterr("Initializing with a NULL key.. are you insane?");
00034         return;
00035     }
00036 
00037     dsa = _dsa;
00038     pub = hexifypub(dsa);
00039     if (priv)
00040         prv = hexifyprv(dsa);
00041 }
00042 
00043 
00044 WvDSAKey::WvDSAKey(WvStringParm keystr, bool priv)
00045 {
00046     init(keystr, priv);
00047 }
00048 
00049 
00050 WvDSAKey::WvDSAKey(int bits)
00051 {
00052     dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
00053     DSA_generate_key(dsa);
00054     pub = hexifypub(dsa);
00055     prv = hexifyprv(dsa);
00056 }
00057 
00058 
00059 WvDSAKey::~WvDSAKey()
00060 {
00061     if (dsa)
00062         DSA_free(dsa);
00063 }
00064 
00065 
00066 bool WvDSAKey::isok() const
00067 {
00068    return dsa && !errstring;
00069 }
00070 
00071 
00072 void WvDSAKey::init(WvStringParm keystr, bool priv)
00073 {
00074     // Start out with everything nulled out...
00075     dsa = NULL;
00076     pub = WvString::null;
00077     prv = WvString::null;
00078     
00079     // unhexify the supplied key
00080     WvDynBuf keybuf;
00081     if (!WvHexDecoder().flushstrbuf(keystr,  keybuf, true) ||
00082         keybuf.used() == 0)
00083     {
00084         seterr("DSA key is not a valid hex string");
00085         return;
00086     }
00087     
00088     size_t keylen = keybuf.used();
00089     const unsigned char *key = keybuf.get(keylen);
00090     
00091     // create the DSA struct
00092     if (priv)
00093     {
00094         dsa = wv_d2i_DSAPrivateKey(NULL, &key, keylen);
00095         if (dsa != NULL)
00096         {
00097             prv = keystr;
00098             pub = hexifypub(dsa);
00099         }
00100     }
00101     else
00102     {
00103         dsa = wv_d2i_DSAPublicKey(NULL, &key, keylen);
00104         if (dsa != NULL)
00105         {
00106             prv = WvString::null;
00107             pub = keystr;
00108         }
00109     }
00110     if (dsa == NULL)
00111         seterr("DSA key is invalid");
00112 }
00113 
00114 
00115 
00116 WvString WvDSAKey::getpem(bool privkey)
00117 {
00118     FILE *fp = tmpfile();
00119     const EVP_CIPHER *enc;
00120     
00121     if (!fp)
00122     {
00123         seterr("Unable to open temporary file!");
00124         return WvString::null;
00125     }
00126 
00127     if (privkey)
00128     {
00129         enc = EVP_get_cipherbyname("dsa");
00130         PEM_write_DSAPrivateKey(fp, dsa, enc,
00131                                NULL, 0, NULL, NULL);
00132     }
00133     else
00134     {
00135         // We should write out the Public Key, which is the DSA Public
00136         // key, as well as the DH generator information.
00137 //      PEM_write_DSAPublicKey(fp, dsa);
00138     }
00139     
00140     WvDynBuf b;
00141     size_t len;
00142     
00143     rewind(fp);
00144     while ((len = fread(b.alloc(1024), 1, 1024, fp)) > 0)
00145         b.unalloc(1024 - len);
00146     b.unalloc(1024 - len);
00147     fclose(fp);
00148 
00149     return b.getstr();
00150 }
00151 
00152 
00153 
00154 WvString WvDSAKey::hexifypub(struct dsa_st *dsa)
00155 {
00156     WvDynBuf keybuf;
00157 
00158     assert(dsa);
00159 
00160     size_t size = i2d_DSAPublicKey(dsa, NULL);
00161     unsigned char *key = keybuf.alloc(size);
00162     size_t newsize = i2d_DSAPublicKey(dsa, & key);
00163     assert(size == newsize);
00164     assert(keybuf.used() == size);
00165 
00166     return WvString(WvHexEncoder().strflushbuf(keybuf, true));
00167 }
00168 
00169 
00170 WvString WvDSAKey::hexifyprv(struct dsa_st *dsa)
00171 {
00172     WvDynBuf keybuf;
00173 
00174     assert(dsa);
00175 
00176     size_t size = i2d_DSAPrivateKey(dsa, NULL);
00177     unsigned char *key = keybuf.alloc(size);
00178     size_t newsize = i2d_DSAPrivateKey(dsa, & key);
00179     assert(size == newsize);
00180 
00181     return WvString(WvHexEncoder().strflushbuf(keybuf, true));
00182 }
00183