Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/crypto/utility_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/crypto/utility_impl.h"
2
3
#include "source/common/common/assert.h"
4
#include "source/common/crypto/crypto_impl.h"
5
6
#include "absl/container/fixed_array.h"
7
#include "absl/strings/ascii.h"
8
#include "absl/strings/str_cat.h"
9
10
namespace Envoy {
11
namespace Common {
12
namespace Crypto {
13
14
110
std::vector<uint8_t> UtilityImpl::getSha256Digest(const Buffer::Instance& buffer) {
15
110
  std::vector<uint8_t> digest(SHA256_DIGEST_LENGTH);
16
110
  bssl::ScopedEVP_MD_CTX ctx;
17
110
  auto rc = EVP_DigestInit(ctx.get(), EVP_sha256());
18
110
  RELEASE_ASSERT(rc == 1, "Failed to init digest context");
19
110
  for (const auto& slice : buffer.getRawSlices()) {
20
110
    rc = EVP_DigestUpdate(ctx.get(), slice.mem_, slice.len_);
21
110
    RELEASE_ASSERT(rc == 1, "Failed to update digest");
22
110
  }
23
110
  rc = EVP_DigestFinal(ctx.get(), digest.data(), nullptr);
24
110
  RELEASE_ASSERT(rc == 1, "Failed to finalize digest");
25
110
  return digest;
26
110
}
27
28
std::vector<uint8_t> UtilityImpl::getSha256Hmac(const std::vector<uint8_t>& key,
29
0
                                                absl::string_view message) {
30
0
  std::vector<uint8_t> hmac(SHA256_DIGEST_LENGTH);
31
0
  const auto ret =
32
0
      HMAC(EVP_sha256(), key.data(), key.size(), reinterpret_cast<const uint8_t*>(message.data()),
33
0
           message.size(), hmac.data(), nullptr);
34
0
  RELEASE_ASSERT(ret != nullptr, "Failed to create HMAC");
35
0
  return hmac;
36
0
}
37
38
const VerificationOutput UtilityImpl::verifySignature(absl::string_view hash, CryptoObject& key,
39
                                                      const std::vector<uint8_t>& signature,
40
2.42k
                                                      const std::vector<uint8_t>& text) {
41
  // Step 1: initialize EVP_MD_CTX
42
2.42k
  bssl::ScopedEVP_MD_CTX ctx;
43
44
  // Step 2: initialize EVP_MD
45
2.42k
  const EVP_MD* md = getHashFunction(hash);
46
47
2.42k
  if (md == nullptr) {
48
1.30k
    return {false, absl::StrCat(hash, " is not supported.")};
49
1.30k
  }
50
  // Step 3: initialize EVP_DigestVerify
51
1.12k
  auto pkey_wrapper = Common::Crypto::Access::getTyped<Common::Crypto::PublicKeyObject>(key);
52
1.12k
  EVP_PKEY* pkey = pkey_wrapper->getEVP_PKEY();
53
54
1.12k
  if (pkey == nullptr) {
55
6
    return {false, "Failed to initialize digest verify."};
56
6
  }
57
58
1.11k
  int ok = EVP_DigestVerifyInit(ctx.get(), nullptr, md, nullptr, pkey);
59
1.11k
  if (!ok) {
60
0
    return {false, "Failed to initialize digest verify."};
61
0
  }
62
63
  // Step 4: verify signature
64
1.11k
  ok = EVP_DigestVerify(ctx.get(), signature.data(), signature.size(), text.data(), text.size());
65
66
  // Step 5: check result
67
1.11k
  if (ok == 1) {
68
1
    return {true, ""};
69
1
  }
70
71
1.11k
  return {false, absl::StrCat("Failed to verify digest. Error code: ", ok)};
72
1.11k
}
73
74
2.42k
CryptoObjectPtr UtilityImpl::importPublicKey(const std::vector<uint8_t>& key) {
75
2.42k
  CBS cbs({key.data(), key.size()});
76
77
2.42k
  return std::make_unique<PublicKeyObject>(EVP_parse_public_key(&cbs));
78
2.42k
}
79
80
2.42k
const EVP_MD* UtilityImpl::getHashFunction(absl::string_view name) {
81
2.42k
  const std::string hash = absl::AsciiStrToLower(name);
82
83
  // Hash algorithms set refers
84
  // https://github.com/google/boringssl/blob/master/include/openssl/digest.h
85
2.42k
  if (hash == "sha1") {
86
944
    return EVP_sha1();
87
1.48k
  } else if (hash == "sha224") {
88
26
    return EVP_sha224();
89
1.45k
  } else if (hash == "sha256") {
90
62
    return EVP_sha256();
91
1.39k
  } else if (hash == "sha384") {
92
43
    return EVP_sha384();
93
1.35k
  } else if (hash == "sha512") {
94
48
    return EVP_sha512();
95
1.30k
  } else {
96
1.30k
    return nullptr;
97
1.30k
  }
98
2.42k
}
99
100
// Register the crypto utility singleton.
101
static Crypto::ScopedUtilitySingleton* utility_ =
102
    new Crypto::ScopedUtilitySingleton(std::make_unique<Crypto::UtilityImpl>());
103
104
} // namespace Crypto
105
} // namespace Common
106
} // namespace Envoy