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
18namespace rtc {
19
20OpenSSLDigest::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
29OpenSSLDigest::~OpenSSLDigest() {
30  EVP_MD_CTX_cleanup(&ctx_);
31}
32
33size_t OpenSSLDigest::Size() const {
34  if (!md_) {
35    return 0;
36  }
37  return EVP_MD_size(md_);
38}
39
40void OpenSSLDigest::Update(const void* buf, size_t len) {
41  if (!md_) {
42    return;
43  }
44  EVP_DigestUpdate(&ctx_, buf, len);
45}
46
47size_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
58bool 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
83bool 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
109bool 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