00001
00002
00003
00004
00005
00006
00007 #include "wvsslhacks.h"
00008 #include "wvrsa.h"
00009 #include "wvhex.h"
00010 #include <assert.h>
00011 #include <openssl/rsa.h>
00012
00013
00014
00015 WvRSAKey::WvRSAKey(const WvRSAKey &k)
00016 {
00017 if (k.prv)
00018 init(k.private_str(), true);
00019 else
00020 init(k.public_str(), false);
00021 }
00022
00023
00024 WvRSAKey::WvRSAKey(struct rsa_st *_rsa, bool priv)
00025 {
00026 if (_rsa == NULL)
00027 {
00028 pub = WvString::null;
00029 prv = WvString::null;
00030 rsa = NULL;
00031 seterr("Initializing with a NULL key.. are you insane?");
00032 return;
00033 }
00034
00035 rsa = _rsa;
00036 pub = hexifypub(rsa);
00037 if (priv)
00038 prv = hexifyprv(rsa);
00039 }
00040
00041
00042 WvRSAKey::WvRSAKey(WvStringParm keystr, bool priv)
00043 {
00044 init(keystr, priv);
00045 }
00046
00047
00048 WvRSAKey::WvRSAKey(int bits)
00049 {
00050 rsa = RSA_generate_key(bits, 0x10001, NULL, NULL);
00051 pub = hexifypub(rsa);
00052 prv = hexifyprv(rsa);
00053 }
00054
00055
00056 WvRSAKey::~WvRSAKey()
00057 {
00058 if (rsa)
00059 RSA_free(rsa);
00060 }
00061
00062
00063 void WvRSAKey::init(WvStringParm keystr, bool priv)
00064 {
00065
00066 rsa = NULL;
00067 pub = WvString::null;
00068 prv = WvString::null;
00069
00070
00071 WvDynBuf keybuf;
00072 if (!WvHexDecoder().flushstrbuf(keystr, keybuf, true) ||
00073 keybuf.used() == 0)
00074 {
00075 seterr("RSA key is not a valid hex string");
00076 return;
00077 }
00078
00079 size_t keylen = keybuf.used();
00080 const unsigned char *key = keybuf.get(keylen);
00081 const unsigned char *p = key;
00082
00083
00084 if (priv)
00085 {
00086 rsa = wv_d2i_RSAPrivateKey(NULL, &p, keylen);
00087 if (rsa != NULL)
00088 {
00089 prv = keystr;
00090 pub = hexifypub(rsa);
00091 }
00092 }
00093 else
00094 {
00095 rsa = wv_d2i_RSAPublicKey(NULL, &p, keylen);
00096 if (rsa != NULL)
00097 {
00098 prv = WvString::null;
00099 pub = keystr;
00100 }
00101 }
00102 if (rsa == NULL)
00103 seterr("RSA key is invalid");
00104 }
00105
00106
00107 #if 0
00108 void WvRSAKey::pem2hex(WvStringParm filename)
00109 {
00110 RSA *rsa = NULL;
00111 FILE *fp;
00112
00113 fp = fopen(filename, "r");
00114
00115 if (!fp)
00116 {
00117 seterr("Unable to open %s!",filename);
00118 return;
00119 }
00120
00121 rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
00122
00123 fclose(fp);
00124
00125 if (!rsa)
00126 {
00127 seterr("Unable to decode PEM File!");
00128 return;
00129 }
00130 else
00131 {
00132 hexify(rsa);
00133 return;
00134 }
00135 }
00136 #endif
00137
00138
00139 WvString WvRSAKey::hexifypub(struct rsa_st *rsa)
00140 {
00141 WvDynBuf keybuf;
00142 size_t size = i2d_RSAPublicKey(rsa, NULL);
00143 unsigned char *key = keybuf.alloc(size);
00144 size_t newsize = i2d_RSAPublicKey(rsa, & key);
00145 assert(size == newsize);
00146
00147 WvString keystr = WvHexEncoder().strflushbuf(keybuf, true);
00148 return keystr;
00149 }
00150
00151
00152 WvString WvRSAKey::hexifyprv(struct rsa_st *rsa)
00153 {
00154 WvDynBuf keybuf;
00155 size_t size = i2d_RSAPrivateKey(rsa, NULL);
00156 unsigned char *key = keybuf.alloc(size);
00157 size_t newsize = i2d_RSAPrivateKey(rsa, & key);
00158 assert(size == newsize);
00159
00160 WvString keystr = WvHexEncoder().strflushbuf(keybuf, true);
00161 return keystr;
00162 }
00163
00164
00165
00166
00167 WvRSAEncoder::WvRSAEncoder(Mode _mode, const WvRSAKey & _key) :
00168 mode(_mode), key(_key)
00169 {
00170 if (key.isok() && key.rsa != NULL)
00171 rsasize = RSA_size(key.rsa);
00172 else
00173 rsasize = 0;
00174 }
00175
00176
00177 WvRSAEncoder::~WvRSAEncoder()
00178 {
00179 }
00180
00181
00182 bool WvRSAEncoder::_reset()
00183 {
00184 return true;
00185 }
00186
00187
00188 bool WvRSAEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00189 {
00190 if (rsasize == 0)
00191 {
00192
00193 in.zap();
00194 return false;
00195 }
00196
00197 bool success = true;
00198 switch (mode)
00199 {
00200 case Encrypt:
00201 case SignEncrypt:
00202 {
00203
00204 const size_t maxchunklen = rsasize - 12;
00205 size_t chunklen;
00206 while ((chunklen = in.used()) != 0)
00207 {
00208 if (chunklen >= maxchunklen)
00209 chunklen = maxchunklen;
00210 else if (! flush)
00211 break;
00212
00213
00214 const unsigned char *data = in.get(chunklen);
00215 unsigned char *crypt = out.alloc(rsasize);
00216 size_t cryptlen = (mode == Encrypt) ?
00217 RSA_public_encrypt(chunklen,
00218 const_cast<unsigned char*>(data), crypt,
00219 key.rsa, RSA_PKCS1_PADDING) :
00220 RSA_private_encrypt(chunklen,
00221 const_cast<unsigned char*>(data), crypt,
00222 key.rsa, RSA_PKCS1_PADDING);
00223 if (cryptlen != rsasize)
00224 {
00225 out.unalloc(rsasize);
00226 success = false;
00227 }
00228 }
00229 break;
00230 }
00231 case Decrypt:
00232 case SignDecrypt:
00233 {
00234 const size_t chunklen = rsasize;
00235 while (in.used() >= chunklen)
00236 {
00237
00238 const unsigned char *crypt = in.get(chunklen);
00239 unsigned char *data = out.alloc(rsasize);
00240 int cryptlen = (mode == Decrypt) ?
00241 RSA_private_decrypt(chunklen,
00242 const_cast<unsigned char*>(crypt), data,
00243 key.rsa, RSA_PKCS1_PADDING) :
00244 RSA_public_decrypt(chunklen,
00245 const_cast<unsigned char*>(crypt), data,
00246 key.rsa, RSA_PKCS1_PADDING);
00247 if (cryptlen == -1)
00248 {
00249 out.unalloc(rsasize);
00250 success = false;
00251 }
00252 else
00253 out.unalloc(rsasize - cryptlen);
00254 }
00255
00256 if (flush && in.used() != 0)
00257 success = false;
00258 break;
00259 }
00260 }
00261 return success;
00262 }
00263
00264
00265
00266
00267 WvRSAStream::WvRSAStream(WvStream *_cloned,
00268 const WvRSAKey &_my_key, const WvRSAKey &_their_key,
00269 WvRSAEncoder::Mode readmode, WvRSAEncoder::Mode writemode) :
00270 WvEncoderStream(_cloned)
00271 {
00272 readchain.append(new WvRSAEncoder(readmode, _my_key), true);
00273 writechain.append(new WvRSAEncoder(writemode, _their_key), true);
00274 if (_my_key.isok() && _my_key.rsa)
00275 min_readsize = RSA_size(_my_key.rsa);
00276 }