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 }