1 /* 2 * libjingle 3 * Copyright 2004--2012, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #if HAVE_OPENSSL_SSL_H 29 30 #include "talk/base/openssldigest.h" 31 32 #include "talk/base/common.h" 33 34 namespace talk_base { 35 36 OpenSSLDigest::OpenSSLDigest(const std::string& algorithm) { 37 EVP_MD_CTX_init(&ctx_); 38 if (GetDigestEVP(algorithm, &md_)) { 39 EVP_DigestInit_ex(&ctx_, md_, NULL); 40 } else { 41 md_ = NULL; 42 } 43 } 44 45 OpenSSLDigest::~OpenSSLDigest() { 46 EVP_MD_CTX_cleanup(&ctx_); 47 } 48 49 size_t OpenSSLDigest::Size() const { 50 if (!md_) { 51 return 0; 52 } 53 return EVP_MD_size(md_); 54 } 55 56 void OpenSSLDigest::Update(const void* buf, size_t len) { 57 if (!md_) { 58 return; 59 } 60 EVP_DigestUpdate(&ctx_, buf, len); 61 } 62 63 size_t OpenSSLDigest::Finish(void* buf, size_t len) { 64 if (!md_ || len < Size()) { 65 return 0; 66 } 67 unsigned int md_len; 68 EVP_DigestFinal_ex(&ctx_, static_cast<unsigned char*>(buf), &md_len); 69 EVP_DigestInit_ex(&ctx_, md_, NULL); // prepare for future Update()s 70 ASSERT(md_len == Size()); 71 return md_len; 72 } 73 74 bool OpenSSLDigest::GetDigestEVP(const std::string& algorithm, 75 const EVP_MD** mdp) { 76 const EVP_MD* md; 77 if (algorithm == DIGEST_MD5) { 78 md = EVP_md5(); 79 } else if (algorithm == DIGEST_SHA_1) { 80 md = EVP_sha1(); 81 #if OPENSSL_VERSION_NUMBER >= 0x00908000L 82 } else if (algorithm == DIGEST_SHA_224) { 83 md = EVP_sha224(); 84 } else if (algorithm == DIGEST_SHA_256) { 85 md = EVP_sha256(); 86 } else if (algorithm == DIGEST_SHA_384) { 87 md = EVP_sha384(); 88 } else if (algorithm == DIGEST_SHA_512) { 89 md = EVP_sha512(); 90 #endif 91 } else { 92 return false; 93 } 94 95 // Can't happen 96 ASSERT(EVP_MD_size(md) >= 16); 97 *mdp = md; 98 return true; 99 } 100 101 bool OpenSSLDigest::GetDigestName(const EVP_MD* md, 102 std::string* algorithm) { 103 ASSERT(md != NULL); 104 ASSERT(algorithm != NULL); 105 106 int md_type = EVP_MD_type(md); 107 if (md_type == NID_md5) { 108 *algorithm = DIGEST_MD5; 109 } else if (md_type == NID_sha1) { 110 *algorithm = DIGEST_SHA_1; 111 #if OPENSSL_VERSION_NUMBER >= 0x00908000L 112 } else if (md_type == NID_sha224) { 113 *algorithm = DIGEST_SHA_224; 114 } else if (md_type == NID_sha256) { 115 *algorithm = DIGEST_SHA_256; 116 } else if (md_type == NID_sha384) { 117 *algorithm = DIGEST_SHA_384; 118 } else if (md_type == NID_sha512) { 119 *algorithm = DIGEST_SHA_512; 120 #endif 121 } else { 122 algorithm->clear(); 123 return false; 124 } 125 126 return true; 127 } 128 129 bool OpenSSLDigest::GetDigestSize(const std::string& algorithm, 130 size_t* length) { 131 const EVP_MD *md; 132 if (!GetDigestEVP(algorithm, &md)) 133 return false; 134 135 *length = EVP_MD_size(md); 136 return true; 137 } 138 139 } // namespace talk_base 140 141 #endif // HAVE_OPENSSL_SSL_H 142 143