8 #include <openssl/rsa.h> 9 #include <openssl/pem.h> 10 #include "wvsslhacks.h" 13 #include "wvfileutils.h" 18 : debug(
"RSA",
WvLog::Debug5)
24 WvRSAKey::WvRSAKey(
const WvRSAKey &k)
25 : debug(
"RSA",
WvLog::Debug5)
30 rsa = RSAPublicKey_dup(k.rsa);
32 rsa = RSAPrivateKey_dup(k.rsa);
36 WvRSAKey::WvRSAKey(
struct rsa_st *_rsa,
bool _priv)
37 : debug(
"RSA",
WvLog::Debug5)
42 debug(
"Initializing with a NULL key.. are you insane?\n");
52 : debug(
"RSA",
WvLog::Debug5)
57 decode(RsaHex, keystr);
59 decode(RsaPubHex, keystr);
65 WvRSAKey::WvRSAKey(
int bits)
66 : debug(
"RSA",
WvLog::Debug5)
68 rsa = RSA_generate_key(bits, 0x10001, NULL, NULL);
80 bool WvRSAKey::isok()
const 82 return rsa && (!priv || RSA_check_key(rsa) == 1);
99 debug(WvLog::Warning,
"Tried to encode RSA key, but RSA key is " 104 if (mode == RsaHex || mode == RsaPubHex)
108 if (mode == RsaHex && priv)
110 size_t size = i2d_RSAPrivateKey(rsa, NULL);
111 unsigned char *key = keybuf.
alloc(size);
112 size_t newsize = i2d_RSAPrivateKey(rsa, & key);
113 assert(size == newsize);
117 size_t size = i2d_RSAPublicKey(rsa, NULL);
118 unsigned char *key = keybuf.
alloc(size);
119 size_t newsize = i2d_RSAPublicKey(rsa, & key);
120 assert(size == newsize);
127 BIO *bufbio = BIO_new(BIO_s_mem());
129 const EVP_CIPHER *enc = EVP_get_cipherbyname(
"rsa");
132 PEM_write_bio_RSAPrivateKey(bufbio, rsa, enc,
133 NULL, 0, NULL, NULL);
134 else if (mode == RsaPubPEM)
135 PEM_write_bio_RSAPublicKey(bufbio, rsa);
137 debug(WvLog::Warning,
"Should never happen: tried to encode RSA " 138 "key with unsupported mode.");
140 BIO_get_mem_ptr(bufbio, &bm);
141 buf.put(bm->data, bm->length);
160 debug(
"Decoding RSA key.\n");
164 debug(
"Replacing already existent RSA key.\n");
172 if (mode == RsaHex || mode == RsaPubHex)
179 debug(
"Couldn't unhexify RSA key.\n");
183 size_t keylen = keybuf.
used();
184 const unsigned char *key = keybuf.
get(keylen);
189 rsa = wv_d2i_RSAPrivateKey(NULL, &key, keylen);
193 rsa = wv_d2i_RSAPublicKey(NULL, &key, keylen);
200 BIO *membuf = BIO_new(BIO_s_mem());
201 BIO_write(membuf, encoded.
get(encoded.
used()), encoded.
used());
205 rsa = PEM_read_bio_RSAPrivateKey(membuf, NULL, NULL, NULL);
208 else if (mode == RsaPubPEM)
209 rsa = PEM_read_bio_RSAPublicKey(membuf, NULL, NULL, NULL);
211 debug(WvLog::Warning,
"Should never happen: tried to encode RSA " 212 "key with unsupported mode.");
214 BIO_free_all(membuf);
222 mode(_mode), key(_key)
224 if (key.isok() && key.rsa != NULL)
225 rsasize = RSA_size(key.rsa);
231 WvRSAEncoder::~WvRSAEncoder()
258 const size_t maxchunklen = rsasize - 12;
260 while ((chunklen = in.
used()) != 0)
262 if (chunklen >= maxchunklen)
263 chunklen = maxchunklen;
268 const unsigned char *data = in.
get(chunklen);
269 unsigned char *crypt = out.
alloc(rsasize);
270 size_t cryptlen = (mode ==
Encrypt) ?
271 RSA_public_encrypt(chunklen,
272 const_cast<unsigned char*>(data), crypt,
273 key.rsa, RSA_PKCS1_PADDING) :
274 RSA_private_encrypt(chunklen,
275 const_cast<unsigned char*>(data), crypt,
276 key.rsa, RSA_PKCS1_PADDING);
277 if (cryptlen != rsasize)
288 const size_t chunklen = rsasize;
289 while (in.
used() >= chunklen)
292 const unsigned char *crypt = in.
get(chunklen);
293 unsigned char *data = out.
alloc(rsasize);
294 int cryptlen = (mode ==
Decrypt) ?
295 RSA_private_decrypt(chunklen,
296 const_cast<unsigned char*>(crypt), data,
297 key.rsa, RSA_PKCS1_PADDING) :
298 RSA_public_decrypt(chunklen,
299 const_cast<unsigned char*>(crypt), data,
300 key.rsa, RSA_PKCS1_PADDING);
307 out.
unalloc(rsasize - cryptlen);
310 if (flush && in.
used() != 0)
321 WvRSAStream::WvRSAStream(
WvStream *_cloned,
326 readchain.append(
new WvRSAEncoder(readmode, _my_key),
true);
327 writechain.append(
new WvRSAEncoder(writemode, _their_key),
true);
328 if (_my_key.isok() && _my_key.rsa)
329 min_readsize = RSA_size(_my_key.rsa);
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
bool flush(WvBuf &inbuf, WvBuf &outbuf, bool finish=false)
Flushes the encoder and optionally finishes it.
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
WvEncoderStream chains a series of encoders on the input and output ports of the underlying stream to...
void unalloc(size_t count)
Unallocates exactly the specified number of elements by removing them from the buffer and releasing t...
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
WvRSAEncoder(Mode mode, const WvRSAKey &key)
Creates a new RSA cipher encoder.
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers...
virtual bool _encode(WvBuf &in, WvBuf &out, bool flush)
Template method implementation of encode().
size_t used() const
Returns the number of elements in the buffer currently available for reading.
void zap()
Clears the buffer.
virtual void decode(const DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
virtual WvString encode(const DumpMode mode) const
Return the information requested by mode.
virtual bool _reset()
Template method implementation of reset().
An RSA public key or public/private key pair that can be used for encryption.
WvString is an implementation of a simple and efficient printable-string class.
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's...
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
Hex functions for compatibility with older code.
DumpMode
Type for the encode() and decode() methods.