xref: /aosp_15_r20/external/webrtc/rtc_base/openssl_digest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #include "rtc_base/openssl_digest.h"
12 
13 #include "absl/strings/string_view.h"
14 #include "rtc_base/checks.h"  // RTC_DCHECK, RTC_CHECK
15 #include "rtc_base/openssl.h"
16 
17 namespace rtc {
18 
OpenSSLDigest(absl::string_view algorithm)19 OpenSSLDigest::OpenSSLDigest(absl::string_view algorithm) {
20   ctx_ = EVP_MD_CTX_new();
21   RTC_CHECK(ctx_ != nullptr);
22   EVP_MD_CTX_init(ctx_);
23   if (GetDigestEVP(algorithm, &md_)) {
24     EVP_DigestInit_ex(ctx_, md_, nullptr);
25   } else {
26     md_ = nullptr;
27   }
28 }
29 
~OpenSSLDigest()30 OpenSSLDigest::~OpenSSLDigest() {
31   EVP_MD_CTX_destroy(ctx_);
32 }
33 
Size() const34 size_t OpenSSLDigest::Size() const {
35   if (!md_) {
36     return 0;
37   }
38   return EVP_MD_size(md_);
39 }
40 
Update(const void * buf,size_t len)41 void OpenSSLDigest::Update(const void* buf, size_t len) {
42   if (!md_) {
43     return;
44   }
45   EVP_DigestUpdate(ctx_, buf, len);
46 }
47 
Finish(void * buf,size_t len)48 size_t OpenSSLDigest::Finish(void* buf, size_t len) {
49   if (!md_ || len < Size()) {
50     return 0;
51   }
52   unsigned int md_len;
53   EVP_DigestFinal_ex(ctx_, static_cast<unsigned char*>(buf), &md_len);
54   EVP_DigestInit_ex(ctx_, md_, nullptr);  // prepare for future Update()s
55   RTC_DCHECK(md_len == Size());
56   return md_len;
57 }
58 
GetDigestEVP(absl::string_view algorithm,const EVP_MD ** mdp)59 bool OpenSSLDigest::GetDigestEVP(absl::string_view algorithm,
60                                  const EVP_MD** mdp) {
61   const EVP_MD* md;
62   if (algorithm == DIGEST_MD5) {
63     md = EVP_md5();
64   } else if (algorithm == DIGEST_SHA_1) {
65     md = EVP_sha1();
66   } else if (algorithm == DIGEST_SHA_224) {
67     md = EVP_sha224();
68   } else if (algorithm == DIGEST_SHA_256) {
69     md = EVP_sha256();
70   } else if (algorithm == DIGEST_SHA_384) {
71     md = EVP_sha384();
72   } else if (algorithm == DIGEST_SHA_512) {
73     md = EVP_sha512();
74   } else {
75     return false;
76   }
77 
78   // Can't happen
79   RTC_DCHECK(EVP_MD_size(md) >= 16);
80   *mdp = md;
81   return true;
82 }
83 
GetDigestName(const EVP_MD * md,std::string * algorithm)84 bool OpenSSLDigest::GetDigestName(const EVP_MD* md, std::string* algorithm) {
85   RTC_DCHECK(md != nullptr);
86   RTC_DCHECK(algorithm != nullptr);
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(absl::string_view algorithm,size_t * length)109 bool OpenSSLDigest::GetDigestSize(absl::string_view algorithm, size_t* length) {
110   const EVP_MD* md;
111   if (!GetDigestEVP(algorithm, &md))
112     return false;
113 
114   *length = EVP_MD_size(md);
115   return true;
116 }
117 
118 }  // namespace rtc
119