WvStreams
wvdigest.cc
00001 /*
00002  * Worldvisions Tunnel Vision Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * MD5, SHA-1 and HMAC digest abstractions.
00006  */
00007 #include <boost/crc.hpp>
00008 #include "wvdigest.h"
00009 #include "wvserialize.h"
00010 #include <openssl/evp.h>
00011 #include <openssl/hmac.h>
00012 #include <assert.h>
00013 #include <zlib.h>
00014 
00015 /***** WvEVPMDDigest *****/
00016 
00017 WvEVPMDDigest::WvEVPMDDigest(const env_md_st *_evpmd) :
00018     evpmd(_evpmd), active(false)
00019 {
00020     evpctx = new EVP_MD_CTX;
00021     _reset();
00022 }
00023 
00024 
00025 WvEVPMDDigest::~WvEVPMDDigest()
00026 {
00027     cleanup();
00028     delete evpctx;
00029 }
00030 
00031 
00032 bool WvEVPMDDigest::_encode(WvBuf &inbuf, WvBuf &outbuf,
00033     bool flush)
00034 {
00035     size_t len;
00036     while ((len = inbuf.optgettable()) != 0)
00037     {
00038         const unsigned char *data = inbuf.get(len);
00039         EVP_DigestUpdate(evpctx, data, len);
00040     }
00041     return true;
00042 }
00043 
00044 
00045 bool WvEVPMDDigest::_finish(WvBuf &outbuf)
00046 {
00047     assert(active);
00048     unsigned char digest[EVP_MAX_MD_SIZE];
00049     unsigned int size; // size_t is not an unsigned int on many 64 bit systems
00050     EVP_DigestFinal(evpctx, digest, & size);
00051     active = false;
00052     outbuf.put(digest, size);
00053     return true;
00054 }
00055 
00056 
00057 bool WvEVPMDDigest::_reset()
00058 {
00059     cleanup();
00060     
00061     // the typecast is necessary for API compatibility with different
00062     // versions of openssl.  None of them *actually* change the contents of
00063     // the pointer.
00064     EVP_DigestInit(evpctx, (env_md_st *)evpmd);
00065     active = true;
00066     return true;
00067 }
00068 
00069 
00070 void WvEVPMDDigest::cleanup()
00071 {
00072     if (active)
00073     {
00074         // discard digest
00075         unsigned char digest[EVP_MAX_MD_SIZE];
00076         EVP_DigestFinal(evpctx, digest, NULL);
00077         active = false;
00078     }
00079 }
00080 
00081 size_t WvEVPMDDigest::digestsize() const
00082 {
00083     return EVP_MD_size((env_md_st *)evpmd);
00084 }
00085 
00086 
00087 /***** WvMD5Digest *****/
00088 
00089 WvMD5Digest::WvMD5Digest() : WvEVPMDDigest(EVP_md5())
00090 {
00091 }
00092 
00093 
00094 /***** WvSHA1Digest *****/
00095 
00096 WvSHA1Digest::WvSHA1Digest() : WvEVPMDDigest(EVP_sha1())
00097 {
00098 }
00099 
00100 /***** WvHMACDigest *****/
00101 
00102 WvHMACDigest::WvHMACDigest(WvEVPMDDigest *_digest,
00103     const void *_key, size_t _keysize) :
00104     digest(_digest), keysize(_keysize), active(false)
00105 {
00106     key = new unsigned char[keysize];
00107     memcpy(key, _key, keysize);
00108     hmacctx = new HMAC_CTX;
00109     _reset();
00110 }
00111 
00112 WvHMACDigest::~WvHMACDigest()
00113 {
00114     cleanup();
00115     delete hmacctx;
00116     deletev key;
00117     delete digest;
00118 }
00119 
00120 
00121 bool WvHMACDigest::_encode(WvBuf &inbuf, WvBuf &outbuf,
00122     bool flush)
00123 {
00124     size_t len;
00125     while ((len = inbuf.optgettable()) != 0)
00126     {
00127         const unsigned char *data = inbuf.get(len);
00128         HMAC_Update(hmacctx, data, len);
00129     }
00130     return true;
00131 }
00132 
00133 
00134 bool WvHMACDigest::_finish(WvBuf &outbuf)
00135 {
00136     assert(active);
00137     unsigned char digest[EVP_MAX_MD_SIZE];
00138     unsigned int size;
00139     HMAC_Final(hmacctx, digest, & size);
00140     active = false;
00141     outbuf.put(digest, size);
00142     return true;
00143 }
00144 
00145 
00146 bool WvHMACDigest::_reset()
00147 {
00148     cleanup();
00149     HMAC_Init(hmacctx, key, keysize, (env_md_st *)digest->getevpmd());
00150     active = true;
00151     return true;
00152 }
00153 
00154 
00155 void WvHMACDigest::cleanup()
00156 {
00157     if (active)
00158     {
00159         // discard digest
00160         unsigned char digest[EVP_MAX_MD_SIZE];
00161         HMAC_Final(hmacctx, digest, NULL);
00162         active = false;
00163     }
00164 }
00165 
00166 
00167 size_t WvHMACDigest::digestsize() const
00168 {
00169     return digest->digestsize();
00170 }
00171 
00172 
00173 WvCrc32Digest::WvCrc32Digest()
00174 {
00175     _reset();
00176 }
00177 
00178 
00179 bool WvCrc32Digest::_encode(WvBuf &inbuf, WvBuf &outbuf, bool flush)
00180 {
00181     size_t len;
00182     while ((len = inbuf.optgettable()) != 0)
00183         crc = crc32(crc, inbuf.get(len), len);
00184     return true;
00185 }
00186 
00187 
00188 bool WvCrc32Digest::_finish(WvBuf &outbuf)
00189 {
00190     wv_serialize(outbuf, crc);
00191     return true;
00192 }
00193 
00194 
00195 bool WvCrc32Digest::_reset()
00196 {
00197     crc = crc32(0, NULL, 0);
00198     return true;
00199 }
00200 
00201 
00202 size_t WvCrc32Digest::digestsize() const
00203 {
00204     return sizeof(crc);
00205 }
00206 
00207 
00208 WvAdler32Digest::WvAdler32Digest()
00209 {
00210     _reset();
00211 }
00212 
00213 
00214 bool WvAdler32Digest::_encode(WvBuf &inbuf, WvBuf &outbuf, bool flush)
00215 {
00216     size_t len;
00217     while ((len = inbuf.optgettable()) != 0)
00218         crc = adler32(crc, inbuf.get(len), len);
00219     return true;
00220 }
00221 
00222 
00223 bool WvAdler32Digest::_finish(WvBuf &outbuf)
00224 {
00225     wv_serialize(outbuf, crc);
00226     return true;
00227 }
00228 
00229 
00230 bool WvAdler32Digest::_reset()
00231 {
00232     crc = adler32(0, NULL, 0);
00233     return true;
00234 }
00235 
00236 
00237 size_t WvAdler32Digest::digestsize() const
00238 {
00239     return sizeof(crc);
00240 }