initial code repo
[stor4nfv.git] / src / ceph / src / common / ceph_crypto.h
diff --git a/src/ceph/src/common/ceph_crypto.h b/src/ceph/src/common/ceph_crypto.h
new file mode 100644 (file)
index 0000000..9c30239
--- /dev/null
@@ -0,0 +1,188 @@
+#ifndef CEPH_CRYPTO_H
+#define CEPH_CRYPTO_H
+
+#include "acconfig.h"
+
+#define CEPH_CRYPTO_MD5_DIGESTSIZE 16
+#define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20
+#define CEPH_CRYPTO_SHA1_DIGESTSIZE 20
+#define CEPH_CRYPTO_HMACSHA256_DIGESTSIZE 32
+#define CEPH_CRYPTO_SHA256_DIGESTSIZE 32
+
+#ifdef USE_CRYPTOPP
+# define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+#include <string.h>
+#include <cryptopp/md5.h>
+#include <cryptopp/sha.h>
+#include <cryptopp/hmac.h>
+
+// reinclude our assert to clobber the system one
+# include "include/assert.h"
+
+namespace ceph {
+  namespace crypto {
+    void assert_init();
+    void init(CephContext *cct);
+    // @param shared true if the the underlying crypto library could be shared
+    //               with the application linked against the Ceph library.
+    // @note we do extra global cleanup specific to the underlying crypto
+    //       library, if @c shared is @c false.
+    void shutdown(bool shared=true);
+
+    using CryptoPP::Weak::MD5;
+    using CryptoPP::SHA1;
+    using CryptoPP::SHA256;
+
+    class HMACSHA1: public CryptoPP::HMAC<CryptoPP::SHA1> {
+    public:
+      HMACSHA1 (const byte *key, size_t length)
+       : CryptoPP::HMAC<CryptoPP::SHA1>(key, length)
+       {
+       }
+      ~HMACSHA1();
+    };
+
+    class HMACSHA256: public CryptoPP::HMAC<CryptoPP::SHA256> {
+    public:
+      HMACSHA256 (const byte *key, size_t length)
+        : CryptoPP::HMAC<CryptoPP::SHA256>(key, length)
+        {
+        }
+      ~HMACSHA256();
+    };
+  }
+}
+#elif defined(USE_NSS)
+// you *must* use CRYPTO_CXXFLAGS in CMakeLists.txt for including this include
+# include <nss.h>
+# include <pk11pub.h>
+
+// NSS thinks a lot of fairly fundamental operations might potentially
+// fail, because it has been written to support e.g. smartcards doing all
+// the crypto operations. We don't want to contaminate too much code
+// with error checking, and just say these really should never fail.
+// This assert MUST NOT be compiled out, even on non-debug builds.
+# include "include/assert.h"
+
+// ugly bit of CryptoPP that we have to emulate here :(
+typedef unsigned char byte;
+
+namespace ceph {
+  namespace crypto {
+    void assert_init();
+    void init(CephContext *cct);
+    void shutdown(bool shared=true);
+    class Digest {
+    private:
+      PK11Context *ctx;
+      size_t digest_size;
+    public:
+      Digest (SECOidTag _type, size_t _digest_size) : digest_size(_digest_size) {
+       ctx = PK11_CreateDigestContext(_type);
+       assert(ctx);
+       Restart();
+      }
+      ~Digest () {
+       PK11_DestroyContext(ctx, PR_TRUE);
+      }
+      void Restart() {
+       SECStatus s;
+       s = PK11_DigestBegin(ctx);
+       assert(s == SECSuccess);
+      }
+      void Update (const byte *input, size_t length) {
+        if (length) {
+         SECStatus s;
+         s = PK11_DigestOp(ctx, input, length);
+         assert(s == SECSuccess);
+        }
+      }
+      void Final (byte *digest) {
+       SECStatus s;
+       unsigned int dummy;
+       s = PK11_DigestFinal(ctx, digest, &dummy, digest_size);
+       assert(s == SECSuccess);
+       assert(dummy == digest_size);
+       Restart();
+      }
+    };
+    class MD5 : public Digest {
+    public:
+      MD5 () : Digest(SEC_OID_MD5, CEPH_CRYPTO_MD5_DIGESTSIZE) { }
+    };
+
+    class SHA1 : public Digest {
+    public:
+      SHA1 () : Digest(SEC_OID_SHA1, CEPH_CRYPTO_SHA1_DIGESTSIZE) { }
+    };
+
+    class SHA256 : public Digest {
+    public:
+      SHA256 () : Digest(SEC_OID_SHA256, CEPH_CRYPTO_SHA256_DIGESTSIZE) { }
+    };
+
+    class HMAC {
+    private:
+      PK11SlotInfo *slot;
+      PK11SymKey *symkey;
+      PK11Context *ctx;
+      unsigned int digest_size;
+    public:
+      HMAC (CK_MECHANISM_TYPE cktype, unsigned int digestsize, const byte *key, size_t length) {
+        digest_size = digestsize;
+       slot = PK11_GetBestSlot(cktype, NULL);
+       assert(slot);
+       SECItem keyItem;
+       keyItem.type = siBuffer;
+       keyItem.data = (unsigned char*)key;
+       keyItem.len = length;
+       symkey = PK11_ImportSymKey(slot, cktype, PK11_OriginUnwrap,
+                                  CKA_SIGN,  &keyItem, NULL);
+       assert(symkey);
+       SECItem param;
+       param.type = siBuffer;
+       param.data = NULL;
+       param.len = 0;
+       ctx = PK11_CreateContextBySymKey(cktype, CKA_SIGN, symkey, &param);
+       assert(ctx);
+       Restart();
+      }
+      ~HMAC ();
+      void Restart() {
+       SECStatus s;
+       s = PK11_DigestBegin(ctx);
+       assert(s == SECSuccess);
+      }
+      void Update (const byte *input, size_t length) {
+       SECStatus s;
+       s = PK11_DigestOp(ctx, input, length);
+       assert(s == SECSuccess);
+      }
+      void Final (byte *digest) {
+       SECStatus s;
+       unsigned int dummy;
+       s = PK11_DigestFinal(ctx, digest, &dummy, digest_size);
+       assert(s == SECSuccess);
+       assert(dummy == digest_size);
+       Restart();
+      }
+    };
+
+    class HMACSHA1 : public HMAC {
+    public:
+      HMACSHA1 (const byte *key, size_t length) : HMAC(CKM_SHA_1_HMAC, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, key, length) { }
+    };
+
+    class HMACSHA256 : public HMAC {
+    public:
+      HMACSHA256 (const byte *key, size_t length) : HMAC(CKM_SHA256_HMAC, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE, key, length) { }
+    };
+  }
+}
+
+#else
+// cppcheck-suppress preprocessorErrorDirective
+# error "No supported crypto implementation found."
+#endif
+
+#endif