1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
8 #include "include/common_fwd.h"
9 #include "include/buffer.h"
10 #include "include/types.h"
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
17 #define CEPH_CRYPTO_SHA512_DIGESTSIZE 64
19 #include <openssl/evp.h>
20 #include <openssl/ossl_typ.h>
21 #include <openssl/hmac.h>
23 #include "include/ceph_assert.h"
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
28 #pragma clang diagnostic push
29 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
32 const EVP_MD
*EVP_md5(void);
33 const EVP_MD
*EVP_sha1(void);
34 const EVP_MD
*EVP_sha256(void);
35 const EVP_MD
*EVP_sha512(void);
38 namespace TOPNSPC::crypto
{
41 void shutdown(bool shared
=true);
43 void zeroize_for_security(void *s
, size_t n
);
45 class DigestException
: public std::runtime_error
48 DigestException(const char* what_arg
) : runtime_error(what_arg
)
55 EVP_MD_CTX
*mpContext
;
58 OpenSSLDigest (const EVP_MD
*_type
);
61 void SetFlags(int flags
);
62 void Update (const unsigned char *input
, size_t length
);
63 void Final (unsigned char *digest
);
66 class MD5
: public OpenSSLDigest
{
68 static constexpr size_t digest_size
= CEPH_CRYPTO_MD5_DIGESTSIZE
;
69 MD5 () : OpenSSLDigest(EVP_md5()) { }
72 class SHA1
: public OpenSSLDigest
{
74 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA1_DIGESTSIZE
;
75 SHA1 () : OpenSSLDigest(EVP_sha1()) { }
78 class SHA256
: public OpenSSLDigest
{
80 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA256_DIGESTSIZE
;
81 SHA256 () : OpenSSLDigest(EVP_sha256()) { }
84 class SHA512
: public OpenSSLDigest
{
86 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA512_DIGESTSIZE
;
87 SHA512 () : OpenSSLDigest(EVP_sha512()) { }
91 # if OPENSSL_VERSION_NUMBER < 0x10100000L
98 HMAC (const EVP_MD
*type
, const unsigned char *key
, size_t length
)
100 // the strict FIPS zeroization doesn't seem to be necessary here.
102 ::TOPNSPC::crypto::zeroize_for_security(&mContext
, sizeof(mContext
));
103 const auto r
= HMAC_Init_ex(&mContext
, key
, length
, mpType
, nullptr);
105 throw DigestException("HMAC_Init_ex() failed");
109 HMAC_CTX_cleanup(&mContext
);
113 const auto r
= HMAC_Init_ex(&mContext
, nullptr, 0, mpType
, nullptr);
115 throw DigestException("HMAC_Init_ex() failed");
118 void Update (const unsigned char *input
, size_t length
) {
120 const auto r
= HMAC_Update(&mContext
, input
, length
);
122 throw DigestException("HMAC_Update() failed");
126 void Final (unsigned char *digest
) {
128 const auto r
= HMAC_Final(&mContext
, digest
, &s
);
130 throw DigestException("HMAC_Final() failed");
140 HMAC (const EVP_MD
*type
, const unsigned char *key
, size_t length
)
141 : mpContext(HMAC_CTX_new()) {
142 const auto r
= HMAC_Init_ex(mpContext
, key
, length
, type
, nullptr);
144 throw DigestException("HMAC_Init_ex() failed");
148 HMAC_CTX_free(mpContext
);
152 const EVP_MD
* const type
= HMAC_CTX_get_md(mpContext
);
153 const auto r
= HMAC_Init_ex(mpContext
, nullptr, 0, type
, nullptr);
155 throw DigestException("HMAC_Init_ex() failed");
158 void Update (const unsigned char *input
, size_t length
) {
160 const auto r
= HMAC_Update(mpContext
, input
, length
);
162 throw DigestException("HMAC_Update() failed");
166 void Final (unsigned char *digest
) {
168 const auto r
= HMAC_Final(mpContext
, digest
, &s
);
170 throw DigestException("HMAC_Final() failed");
174 # endif // OPENSSL_VERSION_NUMBER < 0x10100000L
176 struct HMACSHA1
: public HMAC
{
177 HMACSHA1 (const unsigned char *key
, size_t length
)
178 : HMAC(EVP_sha1(), key
, length
) {
182 struct HMACSHA256
: public HMAC
{
183 HMACSHA256 (const unsigned char *key
, size_t length
)
184 : HMAC(EVP_sha256(), key
, length
) {
195 using ssl::HMACSHA256
;
198 template<class Digest
>
199 auto digest(const ceph::buffer::list
& bl
)
201 unsigned char fingerprint
[Digest::digest_size
];
203 for (auto& p
: bl
.buffers()) {
204 gen
.Update((const unsigned char *)p
.c_str(), p
.length());
206 gen
.Final(fingerprint
);
207 return sha_digest_t
<Digest::digest_size
>{fingerprint
};
211 #pragma clang diagnostic pop
212 #pragma GCC diagnostic pop