1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #if HAVE_OPENSSL_SSL_H
12 
13 #include "webrtc/base/openssldigest.h"
14 
15 #include "webrtc/base/common.h"
16 #include "webrtc/base/openssl.h"
17 
18 namespace rtc {
19 
OpenSSLDigest(const std::string & algorithm)20 OpenSSLDigest::OpenSSLDigest(const std::string& algorithm) {
21   EVP_MD_CTX_init(&ctx_);
22   if (GetDigestEVP(algorithm, &md_)) {
23     EVP_DigestInit_ex(&ctx_, md_, NULL);
24   } else {
25     md_ = NULL;
26   }
27 }
28 
~OpenSSLDigest()29 OpenSSLDigest::~OpenSSLDigest() {
30   EVP_MD_CTX_cleanup(&ctx_);
31 }
32 
Size() const33 size_t OpenSSLDigest::Size() const {
34   if (!md_) {
35     return 0;
36   }
37   return EVP_MD_size(md_);
38 }
39 
Update(const void * buf,size_t len)40 void OpenSSLDigest::Update(const void* buf, size_t len) {
41   if (!md_) {
42     return;
43   }
44   EVP_DigestUpdate(&ctx_, buf, len);
45 }
46 
Finish(void * buf,size_t len)47 size_t OpenSSLDigest::Finish(void* buf, size_t len) {
48   if (!md_ || len < Size()) {
49     return 0;
50   }
51   unsigned int md_len;
52   EVP_DigestFinal_ex(&ctx_, static_cast<unsigned char*>(buf), &md_len);
53   EVP_DigestInit_ex(&ctx_, md_, NULL);  // prepare for future Update()s
54   ASSERT(md_len == Size());
55   return md_len;
56 }
57 
GetDigestEVP(const std::string & algorithm,const EVP_MD ** mdp)58 bool OpenSSLDigest::GetDigestEVP(const std::string& algorithm,
59                                  const EVP_MD** mdp) {
60   const EVP_MD* md;
61   if (algorithm == DIGEST_MD5) {
62     md = EVP_md5();
63   } else if (algorithm == DIGEST_SHA_1) {
64     md = EVP_sha1();
65   } else if (algorithm == DIGEST_SHA_224) {
66     md = EVP_sha224();
67   } else if (algorithm == DIGEST_SHA_256) {
68     md = EVP_sha256();
69   } else if (algorithm == DIGEST_SHA_384) {
70     md = EVP_sha384();
71   } else if (algorithm == DIGEST_SHA_512) {
72     md = EVP_sha512();
73   } else {
74     return false;
75   }
76 
77   // Can't happen
78   ASSERT(EVP_MD_size(md) >= 16);
79   *mdp = md;
80   return true;
81 }
82 
GetDigestName(const EVP_MD * md,std::string * algorithm)83 bool OpenSSLDigest::GetDigestName(const EVP_MD* md,
84                                   std::string* algorithm) {
85   ASSERT(md != NULL);
86   ASSERT(algorithm != NULL);
87 
88   int md_type = EVP_MD_type(md);
89   if (md_type == NID_md5) {
90     *algorithm = DIGEST_MD5;
91   } else if (md_type == NID_sha1) {
92     *algorithm = DIGEST_SHA_1;
93   } else if (md_type == NID_sha224) {
94     *algorithm = DIGEST_SHA_224;
95   } else if (md_type == NID_sha256) {
96     *algorithm = DIGEST_SHA_256;
97   } else if (md_type == NID_sha384) {
98     *algorithm = DIGEST_SHA_384;
99   } else if (md_type == NID_sha512) {
100     *algorithm = DIGEST_SHA_512;
101   } else {
102     algorithm->clear();
103     return false;
104   }
105 
106   return true;
107 }
108 
GetDigestSize(const std::string & algorithm,size_t * length)109 bool OpenSSLDigest::GetDigestSize(const std::string& algorithm,
110                                   size_t* length) {
111   const EVP_MD *md;
112   if (!GetDigestEVP(algorithm, &md))
113     return false;
114 
115   *length = EVP_MD_size(md);
116   return true;
117 }
118 
119 }  // namespace rtc
120 
121 #endif  // HAVE_OPENSSL_SSL_H
122 
123