00001
00002
00003
00004
00005
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
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
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
00075 dsa = NULL;
00076 pub = WvString::null;
00077 prv = WvString::null;
00078
00079
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
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
00136
00137
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