]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
7c673cae FG |
2 | #ifndef CEPH_CRYPTO_H |
3 | #define CEPH_CRYPTO_H | |
4 | ||
5 | #include "acconfig.h" | |
81eedcae | 6 | #include <stdexcept> |
7c673cae | 7 | |
9f95a23c TL |
8 | #include "include/common_fwd.h" |
9 | #include "include/buffer.h" | |
10 | #include "include/types.h" | |
11 | ||
7c673cae FG |
12 | #define CEPH_CRYPTO_MD5_DIGESTSIZE 16 |
13 | #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20 | |
14 | #define CEPH_CRYPTO_SHA1_DIGESTSIZE 20 | |
15 | #define CEPH_CRYPTO_HMACSHA256_DIGESTSIZE 32 | |
16 | #define CEPH_CRYPTO_SHA256_DIGESTSIZE 32 | |
9f95a23c | 17 | #define CEPH_CRYPTO_SHA512_DIGESTSIZE 64 |
7c673cae | 18 | |
11fdf7f2 TL |
19 | #include <openssl/evp.h> |
20 | #include <openssl/ossl_typ.h> | |
21 | #include <openssl/hmac.h> | |
a8e16298 | 22 | |
9f95a23c TL |
23 | #include "include/ceph_assert.h" |
24 | ||
11fdf7f2 TL |
25 | extern "C" { |
26 | const EVP_MD *EVP_md5(void); | |
27 | const EVP_MD *EVP_sha1(void); | |
28 | const EVP_MD *EVP_sha256(void); | |
9f95a23c | 29 | const EVP_MD *EVP_sha512(void); |
11fdf7f2 | 30 | } |
a8e16298 | 31 | |
9f95a23c TL |
32 | namespace TOPNSPC::crypto { |
33 | void assert_init(); | |
34 | void init(); | |
35 | void shutdown(bool shared=true); | |
11fdf7f2 | 36 | |
9f95a23c | 37 | void zeroize_for_security(void *s, size_t n); |
81eedcae | 38 | |
9f95a23c TL |
39 | class DigestException : public std::runtime_error |
40 | { | |
81eedcae TL |
41 | public: |
42 | DigestException(const char* what_arg) : runtime_error(what_arg) | |
43 | {} | |
9f95a23c | 44 | }; |
11fdf7f2 | 45 | |
9f95a23c TL |
46 | namespace ssl { |
47 | class OpenSSLDigest { | |
11fdf7f2 TL |
48 | private: |
49 | EVP_MD_CTX *mpContext; | |
50 | const EVP_MD *mpType; | |
51 | public: | |
52 | OpenSSLDigest (const EVP_MD *_type); | |
53 | ~OpenSSLDigest (); | |
54 | void Restart(); | |
20effc67 | 55 | void SetFlags(int flags); |
11fdf7f2 TL |
56 | void Update (const unsigned char *input, size_t length); |
57 | void Final (unsigned char *digest); | |
9f95a23c | 58 | }; |
11fdf7f2 | 59 | |
9f95a23c | 60 | class MD5 : public OpenSSLDigest { |
11fdf7f2 | 61 | public: |
9f95a23c | 62 | static constexpr size_t digest_size = CEPH_CRYPTO_MD5_DIGESTSIZE; |
11fdf7f2 | 63 | MD5 () : OpenSSLDigest(EVP_md5()) { } |
9f95a23c | 64 | }; |
7c673cae | 65 | |
9f95a23c | 66 | class SHA1 : public OpenSSLDigest { |
11fdf7f2 | 67 | public: |
9f95a23c | 68 | static constexpr size_t digest_size = CEPH_CRYPTO_SHA1_DIGESTSIZE; |
11fdf7f2 | 69 | SHA1 () : OpenSSLDigest(EVP_sha1()) { } |
9f95a23c | 70 | }; |
11fdf7f2 | 71 | |
9f95a23c | 72 | class SHA256 : public OpenSSLDigest { |
11fdf7f2 | 73 | public: |
9f95a23c | 74 | static constexpr size_t digest_size = CEPH_CRYPTO_SHA256_DIGESTSIZE; |
11fdf7f2 | 75 | SHA256 () : OpenSSLDigest(EVP_sha256()) { } |
7c673cae FG |
76 | }; |
77 | ||
9f95a23c TL |
78 | class SHA512 : public OpenSSLDigest { |
79 | public: | |
80 | static constexpr size_t digest_size = CEPH_CRYPTO_SHA512_DIGESTSIZE; | |
81 | SHA512 () : OpenSSLDigest(EVP_sha512()) { } | |
7c673cae FG |
82 | }; |
83 | ||
11fdf7f2 | 84 | |
11fdf7f2 TL |
85 | # if OPENSSL_VERSION_NUMBER < 0x10100000L |
86 | class HMAC { | |
87 | private: | |
88 | HMAC_CTX mContext; | |
89 | const EVP_MD *mpType; | |
90 | ||
91 | public: | |
92 | HMAC (const EVP_MD *type, const unsigned char *key, size_t length) | |
93 | : mpType(type) { | |
92f5a8d4 TL |
94 | // the strict FIPS zeroization doesn't seem to be necessary here. |
95 | // just in the case. | |
9f95a23c | 96 | ::TOPNSPC::crypto::zeroize_for_security(&mContext, sizeof(mContext)); |
11fdf7f2 | 97 | const auto r = HMAC_Init_ex(&mContext, key, length, mpType, nullptr); |
81eedcae TL |
98 | if (r != 1) { |
99 | throw DigestException("HMAC_Init_ex() failed"); | |
100 | } | |
11fdf7f2 TL |
101 | } |
102 | ~HMAC () { | |
103 | HMAC_CTX_cleanup(&mContext); | |
104 | } | |
105 | ||
106 | void Restart () { | |
107 | const auto r = HMAC_Init_ex(&mContext, nullptr, 0, mpType, nullptr); | |
81eedcae TL |
108 | if (r != 1) { |
109 | throw DigestException("HMAC_Init_ex() failed"); | |
110 | } | |
11fdf7f2 TL |
111 | } |
112 | void Update (const unsigned char *input, size_t length) { | |
113 | if (length) { | |
114 | const auto r = HMAC_Update(&mContext, input, length); | |
81eedcae TL |
115 | if (r != 1) { |
116 | throw DigestException("HMAC_Update() failed"); | |
117 | } | |
11fdf7f2 TL |
118 | } |
119 | } | |
120 | void Final (unsigned char *digest) { | |
121 | unsigned int s; | |
122 | const auto r = HMAC_Final(&mContext, digest, &s); | |
81eedcae TL |
123 | if (r != 1) { |
124 | throw DigestException("HMAC_Final() failed"); | |
125 | } | |
11fdf7f2 TL |
126 | } |
127 | }; | |
128 | # else | |
129 | class HMAC { | |
130 | private: | |
131 | HMAC_CTX *mpContext; | |
132 | ||
133 | public: | |
134 | HMAC (const EVP_MD *type, const unsigned char *key, size_t length) | |
135 | : mpContext(HMAC_CTX_new()) { | |
136 | const auto r = HMAC_Init_ex(mpContext, key, length, type, nullptr); | |
81eedcae TL |
137 | if (r != 1) { |
138 | throw DigestException("HMAC_Init_ex() failed"); | |
139 | } | |
11fdf7f2 TL |
140 | } |
141 | ~HMAC () { | |
142 | HMAC_CTX_free(mpContext); | |
143 | } | |
144 | ||
145 | void Restart () { | |
146 | const EVP_MD * const type = HMAC_CTX_get_md(mpContext); | |
147 | const auto r = HMAC_Init_ex(mpContext, nullptr, 0, type, nullptr); | |
81eedcae TL |
148 | if (r != 1) { |
149 | throw DigestException("HMAC_Init_ex() failed"); | |
150 | } | |
11fdf7f2 TL |
151 | } |
152 | void Update (const unsigned char *input, size_t length) { | |
153 | if (length) { | |
154 | const auto r = HMAC_Update(mpContext, input, length); | |
81eedcae TL |
155 | if (r != 1) { |
156 | throw DigestException("HMAC_Update() failed"); | |
157 | } | |
11fdf7f2 TL |
158 | } |
159 | } | |
160 | void Final (unsigned char *digest) { | |
161 | unsigned int s; | |
162 | const auto r = HMAC_Final(mpContext, digest, &s); | |
81eedcae TL |
163 | if (r != 1) { |
164 | throw DigestException("HMAC_Final() failed"); | |
165 | } | |
11fdf7f2 TL |
166 | } |
167 | }; | |
168 | # endif // OPENSSL_VERSION_NUMBER < 0x10100000L | |
169 | ||
170 | struct HMACSHA1 : public HMAC { | |
171 | HMACSHA1 (const unsigned char *key, size_t length) | |
172 | : HMAC(EVP_sha1(), key, length) { | |
173 | } | |
174 | }; | |
175 | ||
176 | struct HMACSHA256 : public HMAC { | |
177 | HMACSHA256 (const unsigned char *key, size_t length) | |
178 | : HMAC(EVP_sha256(), key, length) { | |
179 | } | |
180 | }; | |
181 | } | |
11fdf7f2 | 182 | |
7c673cae | 183 | |
9f95a23c TL |
184 | using ssl::SHA256; |
185 | using ssl::MD5; | |
186 | using ssl::SHA1; | |
187 | using ssl::SHA512; | |
11fdf7f2 | 188 | |
9f95a23c TL |
189 | using ssl::HMACSHA256; |
190 | using ssl::HMACSHA1; | |
11fdf7f2 | 191 | |
9f95a23c TL |
192 | template<class Digest> |
193 | auto digest(const ceph::buffer::list& bl) | |
194 | { | |
195 | unsigned char fingerprint[Digest::digest_size]; | |
196 | Digest gen; | |
197 | for (auto& p : bl.buffers()) { | |
198 | gen.Update((const unsigned char *)p.c_str(), p.length()); | |
11fdf7f2 | 199 | } |
9f95a23c TL |
200 | gen.Final(fingerprint); |
201 | return sha_digest_t<Digest::digest_size>{fingerprint}; | |
202 | } | |
11fdf7f2 | 203 | } |
7c673cae FG |
204 | |
205 | #endif |