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"
26 const EVP_MD
*EVP_md5(void);
27 const EVP_MD
*EVP_sha1(void);
28 const EVP_MD
*EVP_sha256(void);
29 const EVP_MD
*EVP_sha512(void);
32 namespace TOPNSPC::crypto
{
35 void shutdown(bool shared
=true);
37 void zeroize_for_security(void *s
, size_t n
);
39 class DigestException
: public std::runtime_error
42 DigestException(const char* what_arg
) : runtime_error(what_arg
)
49 EVP_MD_CTX
*mpContext
;
52 OpenSSLDigest (const EVP_MD
*_type
);
55 void SetFlags(int flags
);
56 void Update (const unsigned char *input
, size_t length
);
57 void Final (unsigned char *digest
);
60 class MD5
: public OpenSSLDigest
{
62 static constexpr size_t digest_size
= CEPH_CRYPTO_MD5_DIGESTSIZE
;
63 MD5 () : OpenSSLDigest(EVP_md5()) { }
66 class SHA1
: public OpenSSLDigest
{
68 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA1_DIGESTSIZE
;
69 SHA1 () : OpenSSLDigest(EVP_sha1()) { }
72 class SHA256
: public OpenSSLDigest
{
74 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA256_DIGESTSIZE
;
75 SHA256 () : OpenSSLDigest(EVP_sha256()) { }
78 class SHA512
: public OpenSSLDigest
{
80 static constexpr size_t digest_size
= CEPH_CRYPTO_SHA512_DIGESTSIZE
;
81 SHA512 () : OpenSSLDigest(EVP_sha512()) { }
85 # if OPENSSL_VERSION_NUMBER < 0x10100000L
92 HMAC (const EVP_MD
*type
, const unsigned char *key
, size_t length
)
94 // the strict FIPS zeroization doesn't seem to be necessary here.
96 ::TOPNSPC::crypto::zeroize_for_security(&mContext
, sizeof(mContext
));
97 const auto r
= HMAC_Init_ex(&mContext
, key
, length
, mpType
, nullptr);
99 throw DigestException("HMAC_Init_ex() failed");
103 HMAC_CTX_cleanup(&mContext
);
107 const auto r
= HMAC_Init_ex(&mContext
, nullptr, 0, mpType
, nullptr);
109 throw DigestException("HMAC_Init_ex() failed");
112 void Update (const unsigned char *input
, size_t length
) {
114 const auto r
= HMAC_Update(&mContext
, input
, length
);
116 throw DigestException("HMAC_Update() failed");
120 void Final (unsigned char *digest
) {
122 const auto r
= HMAC_Final(&mContext
, digest
, &s
);
124 throw DigestException("HMAC_Final() failed");
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);
138 throw DigestException("HMAC_Init_ex() failed");
142 HMAC_CTX_free(mpContext
);
146 const EVP_MD
* const type
= HMAC_CTX_get_md(mpContext
);
147 const auto r
= HMAC_Init_ex(mpContext
, nullptr, 0, type
, nullptr);
149 throw DigestException("HMAC_Init_ex() failed");
152 void Update (const unsigned char *input
, size_t length
) {
154 const auto r
= HMAC_Update(mpContext
, input
, length
);
156 throw DigestException("HMAC_Update() failed");
160 void Final (unsigned char *digest
) {
162 const auto r
= HMAC_Final(mpContext
, digest
, &s
);
164 throw DigestException("HMAC_Final() failed");
168 # endif // OPENSSL_VERSION_NUMBER < 0x10100000L
170 struct HMACSHA1
: public HMAC
{
171 HMACSHA1 (const unsigned char *key
, size_t length
)
172 : HMAC(EVP_sha1(), key
, length
) {
176 struct HMACSHA256
: public HMAC
{
177 HMACSHA256 (const unsigned char *key
, size_t length
)
178 : HMAC(EVP_sha256(), key
, length
) {
189 using ssl::HMACSHA256
;
192 template<class Digest
>
193 auto digest(const ceph::buffer::list
& bl
)
195 unsigned char fingerprint
[Digest::digest_size
];
197 for (auto& p
: bl
.buffers()) {
198 gen
.Update((const unsigned char *)p
.c_str(), p
.length());
200 gen
.Final(fingerprint
);
201 return sha_digest_t
<Digest::digest_size
>{fingerprint
};