summaryrefslogtreecommitdiff
path: root/src/common/ceph_crypto.h
blob: 52b98b83a6392ef63a839fa9704bd6287b7d1398 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#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_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();
    void shutdown();

    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();
    };
  }
}
#elif USE_NSS
// you *must* use CRYPTO_CXXFLAGS in Makefile.am 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();
    void shutdown();
    class Digest {
    private:
      PK11Context *ctx;
      SECOidTag sec_type;
      size_t digest_size;
    public:
      Digest (SECOidTag _type, size_t _digest_size) : sec_type(_type), 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) {
	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 HMACSHA1 {
    private:
      PK11SlotInfo *slot;
      PK11SymKey *symkey;
      PK11Context *ctx;
    public:
      HMACSHA1 (const byte *key, size_t length) {
	slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL);
	assert(slot);
	SECItem keyItem;
	keyItem.type = siBuffer;
	keyItem.data = (unsigned char*)key;
	keyItem.len = length;
	symkey = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap,
				   CKA_SIGN,  &keyItem, NULL);
	assert(symkey);
	SECItem param;
	param.type = siBuffer;
	param.data = NULL;
	param.len = 0;
	ctx = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, symkey, &param);
	assert(ctx);
	Restart();
      }
      ~HMACSHA1 ();
      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, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
	assert(s == SECSuccess);
	assert(dummy == CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
	Restart();
      }
    };
  }
}

#else
# error "No supported crypto implementation found."
#endif

#endif