Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvrsa.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Tunnel Vision Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * RSA cryptography abstractions. 00006 */ 00007 #include "wvsslhacks.h" 00008 #include "wvrsa.h" 00009 #include "wvhex.h" 00010 #include <assert.h> 00011 #include <openssl/rsa.h> 00012 00013 /***** WvRSAKey *****/ 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 // Start out with everything nulled out... 00066 rsa = NULL; 00067 pub = WvString::null; 00068 prv = WvString::null; 00069 00070 // unhexify the supplied key 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 // create the RSA struct 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 /***** WvRSAEncoder *****/ 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; // BAD KEY! (should assert but would break compatibility) 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 // IGNORE BAD KEY! 00193 in.zap(); 00194 return false; 00195 } 00196 00197 bool success = true; 00198 switch (mode) 00199 { 00200 case Encrypt: 00201 case SignEncrypt: 00202 { 00203 // reserve space for PKCS1_PADDING 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 // encrypt a chunk 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 // decrypt a chunk 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 // flush does not make sense for us here 00256 if (flush && in.used() != 0) 00257 success = false; 00258 break; 00259 } 00260 } 00261 return success; 00262 } 00263 00264 00265 /***** WvRSAStream *****/ 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 }

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7