]>
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 FG |
7 | |
8 | #define CEPH_CRYPTO_MD5_DIGESTSIZE 16 | |
9 | #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20 | |
10 | #define CEPH_CRYPTO_SHA1_DIGESTSIZE 20 | |
11 | #define CEPH_CRYPTO_HMACSHA256_DIGESTSIZE 32 | |
12 | #define CEPH_CRYPTO_SHA256_DIGESTSIZE 32 | |
13 | ||
11fdf7f2 | 14 | #ifdef USE_NSS |
7c673cae FG |
15 | // you *must* use CRYPTO_CXXFLAGS in CMakeLists.txt for including this include |
16 | # include <nss.h> | |
17 | # include <pk11pub.h> | |
18 | ||
19 | // NSS thinks a lot of fairly fundamental operations might potentially | |
20 | // fail, because it has been written to support e.g. smartcards doing all | |
21 | // the crypto operations. We don't want to contaminate too much code | |
22 | // with error checking, and just say these really should never fail. | |
23 | // This assert MUST NOT be compiled out, even on non-debug builds. | |
11fdf7f2 TL |
24 | # include "include/ceph_assert.h" |
25 | #endif /*USE_NSS*/ | |
7c673cae | 26 | |
11fdf7f2 TL |
27 | #ifdef USE_OPENSSL |
28 | #include <openssl/evp.h> | |
29 | #include <openssl/ossl_typ.h> | |
30 | #include <openssl/hmac.h> | |
a8e16298 | 31 | |
11fdf7f2 TL |
32 | extern "C" { |
33 | const EVP_MD *EVP_md5(void); | |
34 | const EVP_MD *EVP_sha1(void); | |
35 | const EVP_MD *EVP_sha256(void); | |
36 | } | |
37 | #endif /*USE_OPENSSL*/ | |
a8e16298 | 38 | |
7c673cae FG |
39 | namespace ceph { |
40 | namespace crypto { | |
41 | void assert_init(); | |
42 | void init(CephContext *cct); | |
43 | void shutdown(bool shared=true); | |
11fdf7f2 TL |
44 | } |
45 | } | |
46 | ||
47 | #ifdef USE_NSS | |
48 | namespace ceph { | |
49 | namespace crypto { | |
81eedcae TL |
50 | |
51 | class DigestException : public std::runtime_error | |
52 | { | |
53 | public: | |
54 | DigestException(const char* what_arg) : runtime_error(what_arg) | |
55 | {} | |
56 | }; | |
57 | ||
11fdf7f2 | 58 | namespace nss { |
81eedcae | 59 | |
11fdf7f2 TL |
60 | class NSSDigest { |
61 | private: | |
62 | PK11Context *ctx; | |
63 | size_t digest_size; | |
64 | public: | |
65 | NSSDigest (SECOidTag _type, size_t _digest_size) | |
66 | : digest_size(_digest_size) { | |
67 | ctx = PK11_CreateDigestContext(_type); | |
81eedcae TL |
68 | if (! ctx) { |
69 | throw DigestException("PK11_CreateDigestContext() failed"); | |
70 | } | |
11fdf7f2 | 71 | Restart(); |
7c673cae | 72 | } |
11fdf7f2 TL |
73 | ~NSSDigest () { |
74 | PK11_DestroyContext(ctx, PR_TRUE); | |
75 | } | |
76 | void Restart() { | |
77 | SECStatus s; | |
78 | s = PK11_DigestBegin(ctx); | |
81eedcae TL |
79 | if (s != SECSuccess) { |
80 | throw DigestException("PK11_DigestBegin() failed"); | |
81 | } | |
11fdf7f2 TL |
82 | } |
83 | void Update (const unsigned char *input, size_t length) { | |
84 | if (length) { | |
85 | SECStatus s; | |
86 | s = PK11_DigestOp(ctx, input, length); | |
81eedcae TL |
87 | if (s != SECSuccess) { |
88 | throw DigestException("PK11_DigestOp() failed"); | |
89 | } | |
11fdf7f2 TL |
90 | } |
91 | } | |
92 | void Final (unsigned char *digest) { | |
93 | SECStatus s; | |
94 | unsigned int dummy; | |
95 | s = PK11_DigestFinal(ctx, digest, &dummy, digest_size); | |
81eedcae TL |
96 | if (! (s == SECSuccess) && |
97 | (dummy == digest_size)) { | |
98 | throw DigestException("PK11_DigestFinal() failed"); | |
99 | } | |
11fdf7f2 TL |
100 | Restart(); |
101 | } | |
102 | }; | |
7c673cae | 103 | |
11fdf7f2 TL |
104 | class MD5 : public NSSDigest { |
105 | public: | |
106 | MD5 () : NSSDigest(SEC_OID_MD5, CEPH_CRYPTO_MD5_DIGESTSIZE) { } | |
107 | }; | |
7c673cae | 108 | |
11fdf7f2 TL |
109 | class SHA1 : public NSSDigest { |
110 | public: | |
111 | SHA1 () : NSSDigest(SEC_OID_SHA1, CEPH_CRYPTO_SHA1_DIGESTSIZE) { } | |
112 | }; | |
113 | ||
114 | class SHA256 : public NSSDigest { | |
115 | public: | |
116 | SHA256 () : NSSDigest(SEC_OID_SHA256, CEPH_CRYPTO_SHA256_DIGESTSIZE) { } | |
117 | }; | |
118 | } | |
119 | } | |
120 | } | |
121 | #endif /*USE_NSS*/ | |
122 | ||
123 | #ifdef USE_OPENSSL | |
124 | namespace ceph { | |
125 | namespace crypto { | |
126 | namespace ssl { | |
127 | class OpenSSLDigest { | |
128 | private: | |
129 | EVP_MD_CTX *mpContext; | |
130 | const EVP_MD *mpType; | |
131 | public: | |
132 | OpenSSLDigest (const EVP_MD *_type); | |
133 | ~OpenSSLDigest (); | |
134 | void Restart(); | |
135 | void Update (const unsigned char *input, size_t length); | |
136 | void Final (unsigned char *digest); | |
137 | }; | |
138 | ||
139 | class MD5 : public OpenSSLDigest { | |
140 | public: | |
141 | MD5 () : OpenSSLDigest(EVP_md5()) { } | |
142 | }; | |
7c673cae | 143 | |
11fdf7f2 TL |
144 | class SHA1 : public OpenSSLDigest { |
145 | public: | |
146 | SHA1 () : OpenSSLDigest(EVP_sha1()) { } | |
147 | }; | |
148 | ||
149 | class SHA256 : public OpenSSLDigest { | |
150 | public: | |
151 | SHA256 () : OpenSSLDigest(EVP_sha256()) { } | |
152 | }; | |
153 | } | |
154 | } | |
155 | } | |
156 | #endif /*USE_OPENSSL*/ | |
157 | ||
158 | ||
159 | #ifdef USE_NSS | |
160 | namespace ceph { | |
161 | namespace crypto::nss { | |
7c673cae FG |
162 | class HMAC { |
163 | private: | |
164 | PK11SlotInfo *slot; | |
165 | PK11SymKey *symkey; | |
166 | PK11Context *ctx; | |
167 | unsigned int digest_size; | |
168 | public: | |
11fdf7f2 | 169 | HMAC (CK_MECHANISM_TYPE cktype, unsigned int digestsize, const unsigned char *key, size_t length) { |
7c673cae FG |
170 | digest_size = digestsize; |
171 | slot = PK11_GetBestSlot(cktype, NULL); | |
81eedcae TL |
172 | if (! slot) { |
173 | throw DigestException("PK11_GetBestSlot() failed"); | |
174 | } | |
7c673cae FG |
175 | SECItem keyItem; |
176 | keyItem.type = siBuffer; | |
177 | keyItem.data = (unsigned char*)key; | |
178 | keyItem.len = length; | |
11fdf7f2 TL |
179 | symkey = PK11_ImportSymKey(slot, cktype, PK11_OriginUnwrap, |
180 | CKA_SIGN, &keyItem, NULL); | |
81eedcae TL |
181 | if (! symkey) { |
182 | throw DigestException("PK11_ImportSymKey() failed"); | |
183 | } | |
7c673cae FG |
184 | SECItem param; |
185 | param.type = siBuffer; | |
186 | param.data = NULL; | |
187 | param.len = 0; | |
188 | ctx = PK11_CreateContextBySymKey(cktype, CKA_SIGN, symkey, ¶m); | |
81eedcae TL |
189 | if (! ctx) { |
190 | throw DigestException("PK11_CreateContextBySymKey() failed"); | |
191 | } | |
7c673cae FG |
192 | Restart(); |
193 | } | |
194 | ~HMAC (); | |
195 | void Restart() { | |
196 | SECStatus s; | |
197 | s = PK11_DigestBegin(ctx); | |
81eedcae TL |
198 | if (s != SECSuccess) { |
199 | throw DigestException("PK11_DigestBegin() failed"); | |
200 | } | |
7c673cae | 201 | } |
11fdf7f2 | 202 | void Update (const unsigned char *input, size_t length) { |
7c673cae FG |
203 | SECStatus s; |
204 | s = PK11_DigestOp(ctx, input, length); | |
81eedcae TL |
205 | if (s != SECSuccess) { |
206 | throw DigestException("PK11_DigestOp() failed"); | |
207 | } | |
7c673cae | 208 | } |
11fdf7f2 | 209 | void Final (unsigned char *digest) { |
7c673cae FG |
210 | SECStatus s; |
211 | unsigned int dummy; | |
212 | s = PK11_DigestFinal(ctx, digest, &dummy, digest_size); | |
81eedcae TL |
213 | if (! (s == SECSuccess) && |
214 | (dummy == digest_size)) { | |
215 | throw DigestException("PK11_DigestFinal() failed"); | |
216 | } | |
7c673cae FG |
217 | Restart(); |
218 | } | |
219 | }; | |
220 | ||
221 | class HMACSHA1 : public HMAC { | |
222 | public: | |
11fdf7f2 | 223 | HMACSHA1 (const unsigned char *key, size_t length) : HMAC(CKM_SHA_1_HMAC, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, key, length) { } |
7c673cae FG |
224 | }; |
225 | ||
226 | class HMACSHA256 : public HMAC { | |
227 | public: | |
11fdf7f2 | 228 | HMACSHA256 (const unsigned char *key, size_t length) : HMAC(CKM_SHA256_HMAC, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE, key, length) { } |
7c673cae FG |
229 | }; |
230 | } | |
231 | } | |
11fdf7f2 TL |
232 | #endif |
233 | ||
234 | #ifdef USE_OPENSSL | |
235 | namespace ceph::crypto::ssl { | |
236 | # if OPENSSL_VERSION_NUMBER < 0x10100000L | |
237 | class HMAC { | |
238 | private: | |
239 | HMAC_CTX mContext; | |
240 | const EVP_MD *mpType; | |
241 | ||
242 | public: | |
243 | HMAC (const EVP_MD *type, const unsigned char *key, size_t length) | |
244 | : mpType(type) { | |
245 | ::memset(&mContext, 0, sizeof(mContext)); | |
246 | const auto r = HMAC_Init_ex(&mContext, key, length, mpType, nullptr); | |
81eedcae TL |
247 | if (r != 1) { |
248 | throw DigestException("HMAC_Init_ex() failed"); | |
249 | } | |
11fdf7f2 TL |
250 | } |
251 | ~HMAC () { | |
252 | HMAC_CTX_cleanup(&mContext); | |
253 | } | |
254 | ||
255 | void Restart () { | |
256 | const auto r = HMAC_Init_ex(&mContext, nullptr, 0, mpType, nullptr); | |
81eedcae TL |
257 | if (r != 1) { |
258 | throw DigestException("HMAC_Init_ex() failed"); | |
259 | } | |
11fdf7f2 TL |
260 | } |
261 | void Update (const unsigned char *input, size_t length) { | |
262 | if (length) { | |
263 | const auto r = HMAC_Update(&mContext, input, length); | |
81eedcae TL |
264 | if (r != 1) { |
265 | throw DigestException("HMAC_Update() failed"); | |
266 | } | |
11fdf7f2 TL |
267 | } |
268 | } | |
269 | void Final (unsigned char *digest) { | |
270 | unsigned int s; | |
271 | const auto r = HMAC_Final(&mContext, digest, &s); | |
81eedcae TL |
272 | if (r != 1) { |
273 | throw DigestException("HMAC_Final() failed"); | |
274 | } | |
11fdf7f2 TL |
275 | } |
276 | }; | |
277 | # else | |
278 | class HMAC { | |
279 | private: | |
280 | HMAC_CTX *mpContext; | |
281 | ||
282 | public: | |
283 | HMAC (const EVP_MD *type, const unsigned char *key, size_t length) | |
284 | : mpContext(HMAC_CTX_new()) { | |
285 | const auto r = HMAC_Init_ex(mpContext, key, length, type, nullptr); | |
81eedcae TL |
286 | if (r != 1) { |
287 | throw DigestException("HMAC_Init_ex() failed"); | |
288 | } | |
11fdf7f2 TL |
289 | } |
290 | ~HMAC () { | |
291 | HMAC_CTX_free(mpContext); | |
292 | } | |
293 | ||
294 | void Restart () { | |
295 | const EVP_MD * const type = HMAC_CTX_get_md(mpContext); | |
296 | const auto r = HMAC_Init_ex(mpContext, nullptr, 0, type, nullptr); | |
81eedcae TL |
297 | if (r != 1) { |
298 | throw DigestException("HMAC_Init_ex() failed"); | |
299 | } | |
11fdf7f2 TL |
300 | } |
301 | void Update (const unsigned char *input, size_t length) { | |
302 | if (length) { | |
303 | const auto r = HMAC_Update(mpContext, input, length); | |
81eedcae TL |
304 | if (r != 1) { |
305 | throw DigestException("HMAC_Update() failed"); | |
306 | } | |
11fdf7f2 TL |
307 | } |
308 | } | |
309 | void Final (unsigned char *digest) { | |
310 | unsigned int s; | |
311 | const auto r = HMAC_Final(mpContext, digest, &s); | |
81eedcae TL |
312 | if (r != 1) { |
313 | throw DigestException("HMAC_Final() failed"); | |
314 | } | |
11fdf7f2 TL |
315 | } |
316 | }; | |
317 | # endif // OPENSSL_VERSION_NUMBER < 0x10100000L | |
318 | ||
319 | struct HMACSHA1 : public HMAC { | |
320 | HMACSHA1 (const unsigned char *key, size_t length) | |
321 | : HMAC(EVP_sha1(), key, length) { | |
322 | } | |
323 | }; | |
324 | ||
325 | struct HMACSHA256 : public HMAC { | |
326 | HMACSHA256 (const unsigned char *key, size_t length) | |
327 | : HMAC(EVP_sha256(), key, length) { | |
328 | } | |
329 | }; | |
330 | } | |
331 | #endif /*USE_OPENSSL*/ | |
332 | ||
7c673cae | 333 | |
11fdf7f2 TL |
334 | #if defined(USE_OPENSSL) |
335 | namespace ceph { | |
336 | namespace crypto { | |
337 | using ceph::crypto::ssl::SHA256; | |
338 | using ceph::crypto::ssl::MD5; | |
339 | using ceph::crypto::ssl::SHA1; | |
340 | ||
341 | using ceph::crypto::ssl::HMACSHA256; | |
342 | using ceph::crypto::ssl::HMACSHA1; | |
343 | } | |
344 | } | |
345 | #elif defined(USE_NSS) | |
346 | namespace ceph { | |
347 | namespace crypto { | |
348 | using ceph::crypto::nss::SHA256; | |
349 | using ceph::crypto::nss::MD5; | |
350 | using ceph::crypto::nss::SHA1; | |
351 | ||
352 | using ceph::crypto::nss::HMACSHA256; | |
353 | using ceph::crypto::nss::HMACSHA1; | |
354 | } | |
355 | } | |
7c673cae FG |
356 | #else |
357 | // cppcheck-suppress preprocessorErrorDirective | |
358 | # error "No supported crypto implementation found." | |
359 | #endif | |
360 | ||
361 | #endif |