]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
e8c59f2d | 22 | #pragma once |
e21df721 | 23 | |
ec47cf6f FM |
24 | #include "config.h" |
25 | #include <array> | |
26 | #include <memory> | |
27 | #include <stdexcept> | |
8b474616 | 28 | #include <string> |
dd133337 | 29 | #include <openssl/sha.h> |
e21df721 | 30 | #include <openssl/evp.h> |
8b474616 | 31 | |
ec47cf6f FM |
32 | namespace pdns |
33 | { | |
34 | inline std::string sha1sum(const std::string& input) | |
8b474616 | 35 | { |
ec47cf6f FM |
36 | std::array<unsigned char, 20> result{}; |
37 | // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. | |
38 | SHA1(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result.data()); | |
39 | return {result.begin(), result.end()}; | |
dd133337 | 40 | } |
8b474616 | 41 | |
ec47cf6f | 42 | inline std::string sha256sum(const std::string& input) |
8b474616 | 43 | { |
ec47cf6f FM |
44 | std::array<unsigned char, 32> result{}; |
45 | // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. | |
46 | SHA256(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result.data()); | |
47 | return {result.begin(), result.end()}; | |
dd133337 | 48 | } |
8b474616 | 49 | |
ec47cf6f | 50 | inline std::string sha384sum(const std::string& input) |
8b474616 | 51 | { |
ec47cf6f FM |
52 | std::array<unsigned char, 48> result{}; |
53 | // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. | |
54 | SHA384(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result.data()); | |
55 | return {result.begin(), result.end()}; | |
dd133337 | 56 | } |
8b474616 | 57 | |
ec47cf6f | 58 | inline std::string sha512sum(const std::string& input) |
8b474616 | 59 | { |
ec47cf6f FM |
60 | std::array<unsigned char, 64> result{}; |
61 | // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. | |
62 | SHA512(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), result.data()); | |
63 | return {result.begin(), result.end()}; | |
dd133337 | 64 | } |
e21df721 | 65 | |
2eaaa7c1 O |
66 | class SHADigest |
67 | { | |
68 | public: | |
ddeea7a6 KM |
69 | SHADigest() : |
70 | SHADigest(256) {} | |
4f8ef7a2 | 71 | SHADigest(unsigned int bits) : |
74848abf | 72 | #if defined(HAVE_EVP_MD_CTX_NEW) && defined(HAVE_EVP_MD_CTX_FREE) |
32a499f8 | 73 | mdctx(std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), EVP_MD_CTX_free)) |
d9c81911 | 74 | #else |
74848abf OM |
75 | mdctx(std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), EVP_MD_CTX_destroy)) |
76 | #endif | |
e21df721 | 77 | { |
2eaaa7c1 | 78 | if (mdctx == nullptr) { |
01498d87 | 79 | throw std::runtime_error("SHADigest: EVP_MD_CTX_new failed"); |
2eaaa7c1 O |
80 | } |
81 | switch (bits) { | |
82 | case 256: | |
83 | md = EVP_sha256(); | |
84 | break; | |
85 | case 384: | |
86 | md = EVP_sha384(); | |
87 | break; | |
88 | case 512: | |
89 | md = EVP_sha512(); | |
90 | break; | |
91 | default: | |
a2a7b1db | 92 | throw std::invalid_argument("SHADigest: unsupported size"); |
e21df721 | 93 | } |
ec47cf6f | 94 | if (EVP_DigestInit_ex(mdctx.get(), md, nullptr) == 0) { |
2eaaa7c1 O |
95 | throw std::runtime_error("SHADigest: init error"); |
96 | } | |
97 | } | |
e21df721 | 98 | |
abb11ca4 RP |
99 | // No free of md needed and mdctx is cleaned up by unique_ptr |
100 | ~SHADigest() = default; | |
e21df721 | 101 | |
01498d87 | 102 | void process(const std::string& msg) |
2eaaa7c1 | 103 | { |
4f8ef7a2 | 104 | if (EVP_DigestUpdate(mdctx.get(), msg.data(), msg.size()) == 0) { |
2eaaa7c1 | 105 | throw std::runtime_error("SHADigest: update error"); |
e21df721 | 106 | } |
2eaaa7c1 | 107 | } |
e21df721 | 108 | |
2eaaa7c1 O |
109 | std::string digest() |
110 | { | |
111 | std::string md_value; | |
112 | md_value.resize(EVP_MD_size(md)); | |
ec47cf6f | 113 | unsigned int md_len = 0; |
4f8ef7a2 | 114 | if (EVP_DigestFinal_ex(mdctx.get(), reinterpret_cast<unsigned char*>(md_value.data()), &md_len) == 0) { |
2eaaa7c1 | 115 | throw std::runtime_error("SHADigest: finalize error"); |
e21df721 | 116 | } |
2eaaa7c1 | 117 | if (md_len != md_value.size()) { |
01498d87 | 118 | throw std::runtime_error("SHADigest: inconsistent size"); |
2eaaa7c1 O |
119 | } |
120 | return md_value; | |
121 | } | |
122 | ||
123 | private: | |
74848abf | 124 | #if defined(HAVE_EVP_MD_CTX_NEW) && defined(HAVE_EVP_MD_CTX_FREE) |
32a499f8 | 125 | std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> mdctx; |
74848abf OM |
126 | #else |
127 | std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> mdctx; | |
128 | #endif | |
2eaaa7c1 O |
129 | const EVP_MD* md; |
130 | }; | |
e21df721 | 131 | } |