]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crypto.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / test / crypto.cc
CommitLineData
7c673cae
FG
1#include <errno.h>
2#include <time.h>
3
11fdf7f2
TL
4#include <boost/container/small_vector.hpp>
5
7c673cae
FG
6#include "gtest/gtest.h"
7#include "include/types.h"
8#include "auth/Crypto.h"
9#include "common/Clock.h"
10#include "common/ceph_crypto.h"
11#include "common/ceph_context.h"
12#include "global/global_context.h"
13
20effc67 14using namespace std;
11fdf7f2 15
7c673cae
FG
16class CryptoEnvironment: public ::testing::Environment {
17public:
18 void SetUp() override {
9f95a23c 19 ceph::crypto::init();
7c673cae
FG
20 }
21};
22
23TEST(AES, ValidateSecret) {
24 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
25 int l;
26
27 for (l=0; l<16; l++) {
28 bufferptr bp(l);
29 int err;
30 err = h->validate_secret(bp);
31 EXPECT_EQ(-EINVAL, err);
32 }
33
34 for (l=16; l<50; l++) {
35 bufferptr bp(l);
36 int err;
37 err = h->validate_secret(bp);
38 EXPECT_EQ(0, err);
39 }
40}
41
42TEST(AES, Encrypt) {
43 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
44 char secret_s[] = {
45 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
46 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
47 };
48 bufferptr secret(secret_s, sizeof(secret_s));
49
50 unsigned char plaintext_s[] = {
51 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
52 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
53 };
54 bufferlist plaintext;
55 plaintext.append((char *)plaintext_s, sizeof(plaintext_s));
56
57 bufferlist cipher;
58 std::string error;
59 CryptoKeyHandler *kh = h->get_key_handler(secret, error);
60 int r = kh->encrypt(plaintext, cipher, &error);
61 ASSERT_EQ(r, 0);
62 ASSERT_EQ(error, "");
63
64 unsigned char want_cipher[] = {
65 0xb3, 0x8f, 0x5b, 0xc9, 0x35, 0x4c, 0xf8, 0xc6,
66 0x13, 0x15, 0x66, 0x6f, 0x37, 0xd7, 0x79, 0x3a,
67 0x11, 0x90, 0x7b, 0xe9, 0xd8, 0x3c, 0x35, 0x70,
68 0x58, 0x7b, 0x97, 0x9b, 0x03, 0xd2, 0xa5, 0x01,
69 };
70 char cipher_s[sizeof(want_cipher)];
71
72 ASSERT_EQ(sizeof(cipher_s), cipher.length());
9f95a23c 73 cipher.cbegin().copy(sizeof(cipher_s), &cipher_s[0]);
7c673cae
FG
74
75 int err;
76 err = memcmp(cipher_s, want_cipher, sizeof(want_cipher));
77 ASSERT_EQ(0, err);
78
79 delete kh;
80}
81
11fdf7f2
TL
82TEST(AES, EncryptNoBl) {
83 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
84 char secret_s[] = {
85 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
86 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
87 };
88 bufferptr secret(secret_s, sizeof(secret_s));
89
90 const unsigned char plaintext[] = {
91 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
92 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
93 };
94
95 std::string error;
96 std::unique_ptr<CryptoKeyHandler> kh(h->get_key_handler(secret, error));
97
98 const CryptoKey::in_slice_t plain_slice { sizeof(plaintext), plaintext };
99
100 // we need to deduce size first
101 const CryptoKey::out_slice_t probe_slice { 0, nullptr };
102 const auto needed = kh->encrypt(plain_slice, probe_slice);
103 ASSERT_GE(needed, plain_slice.length);
104
105 boost::container::small_vector<
106 // FIXME?
107 //unsigned char, sizeof(plaintext) + kh->get_block_size()> buf;
108 unsigned char, sizeof(plaintext) + 16> buf(needed);
109 const CryptoKey::out_slice_t cipher_slice { needed, buf.data() };
110 const auto cipher_size = kh->encrypt(plain_slice, cipher_slice);
111 ASSERT_EQ(cipher_size, needed);
112
113 const unsigned char want_cipher[] = {
114 0xb3, 0x8f, 0x5b, 0xc9, 0x35, 0x4c, 0xf8, 0xc6,
115 0x13, 0x15, 0x66, 0x6f, 0x37, 0xd7, 0x79, 0x3a,
116 0x11, 0x90, 0x7b, 0xe9, 0xd8, 0x3c, 0x35, 0x70,
117 0x58, 0x7b, 0x97, 0x9b, 0x03, 0xd2, 0xa5, 0x01,
118 };
119
120 ASSERT_EQ(sizeof(want_cipher), cipher_size);
121
122 const int err = memcmp(buf.data(), want_cipher, sizeof(want_cipher));
123 ASSERT_EQ(0, err);
124}
125
7c673cae
FG
126TEST(AES, Decrypt) {
127 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
128 char secret_s[] = {
129 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
130 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
131 };
132 bufferptr secret(secret_s, sizeof(secret_s));
133
134 unsigned char cipher_s[] = {
135 0xb3, 0x8f, 0x5b, 0xc9, 0x35, 0x4c, 0xf8, 0xc6,
136 0x13, 0x15, 0x66, 0x6f, 0x37, 0xd7, 0x79, 0x3a,
137 0x11, 0x90, 0x7b, 0xe9, 0xd8, 0x3c, 0x35, 0x70,
138 0x58, 0x7b, 0x97, 0x9b, 0x03, 0xd2, 0xa5, 0x01,
139 };
140 bufferlist cipher;
141 cipher.append((char *)cipher_s, sizeof(cipher_s));
142
143 unsigned char want_plaintext[] = {
144 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
145 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
146 };
147 char plaintext_s[sizeof(want_plaintext)];
148
149 std::string error;
150 bufferlist plaintext;
151 CryptoKeyHandler *kh = h->get_key_handler(secret, error);
152 int r = kh->decrypt(cipher, plaintext, &error);
153 ASSERT_EQ(r, 0);
154 ASSERT_EQ(error, "");
155
156 ASSERT_EQ(sizeof(plaintext_s), plaintext.length());
9f95a23c 157 plaintext.cbegin().copy(sizeof(plaintext_s), &plaintext_s[0]);
7c673cae
FG
158
159 int err;
160 err = memcmp(plaintext_s, want_plaintext, sizeof(want_plaintext));
161 ASSERT_EQ(0, err);
162
163 delete kh;
164}
165
11fdf7f2
TL
166TEST(AES, DecryptNoBl) {
167 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
168 const char secret_s[] = {
169 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
170 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
171 };
7c673cae
FG
172 bufferptr secret(secret_s, sizeof(secret_s));
173
11fdf7f2
TL
174 const unsigned char ciphertext[] = {
175 0xb3, 0x8f, 0x5b, 0xc9, 0x35, 0x4c, 0xf8, 0xc6,
176 0x13, 0x15, 0x66, 0x6f, 0x37, 0xd7, 0x79, 0x3a,
177 0x11, 0x90, 0x7b, 0xe9, 0xd8, 0x3c, 0x35, 0x70,
178 0x58, 0x7b, 0x97, 0x9b, 0x03, 0xd2, 0xa5, 0x01,
179 };
180
181 const unsigned char want_plaintext[] = {
182 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
183 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
184 };
185 constexpr static std::size_t plain_buf_size = \
186 CryptoKey::get_max_outbuf_size(sizeof(want_plaintext));
187 unsigned char plaintext[plain_buf_size];
188
189 std::string error;
190 std::unique_ptr<CryptoKeyHandler> kh(h->get_key_handler(secret, error));
191
192 CryptoKey::in_slice_t cipher_slice { sizeof(ciphertext), ciphertext };
193 CryptoKey::out_slice_t plain_slice { sizeof(plaintext), plaintext };
194 const auto plain_size = kh->decrypt(cipher_slice, plain_slice);
195
196 ASSERT_EQ(plain_size, sizeof(want_plaintext));
197
198 const int err = memcmp(plaintext, want_plaintext, sizeof(plain_size));
7c673cae 199 ASSERT_EQ(0, err);
11fdf7f2
TL
200}
201
202template <std::size_t TextSizeV>
203static void aes_loop_cephx() {
204 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
205
206 CryptoRandom random;
207
208 bufferptr secret(16);
209 random.get_bytes(secret.c_str(), secret.length());
210 std::string error;
211 std::unique_ptr<CryptoKeyHandler> kh(h->get_key_handler(secret, error));
212
213 unsigned char plaintext[TextSizeV];
214 random.get_bytes(reinterpret_cast<char*>(plaintext), sizeof(plaintext));
215
216 const CryptoKey::in_slice_t plain_slice { sizeof(plaintext), plaintext };
217
218 // we need to deduce size first
219 const CryptoKey::out_slice_t probe_slice { 0, nullptr };
220 const auto needed = kh->encrypt(plain_slice, probe_slice);
221 ASSERT_GE(needed, plain_slice.length);
222
223 boost::container::small_vector<
224 // FIXME?
225 //unsigned char, sizeof(plaintext) + kh->get_block_size()> buf;
226 unsigned char, sizeof(plaintext) + 16> buf(needed);
227
228 std::size_t cipher_size;
229 for (std::size_t i = 0; i < 1000000; i++) {
230 const CryptoKey::out_slice_t cipher_slice { needed, buf.data() };
231 cipher_size = kh->encrypt(plain_slice, cipher_slice);
232 ASSERT_EQ(cipher_size, needed);
233 }
234}
235
236// These magics reflects Cephx's signature size. Please consult
237// CephxSessionHandler::_calc_signature() for more details.
238TEST(AES, LoopCephx) {
239 aes_loop_cephx<29>();
240}
241
242TEST(AES, LoopCephxV2) {
243 aes_loop_cephx<32>();
244}
245
246static void aes_loop(const std::size_t text_size) {
247 CryptoRandom random;
248
249 bufferptr secret(16);
250 random.get_bytes(secret.c_str(), secret.length());
251
252 bufferptr orig_plaintext(text_size);
253 random.get_bytes(orig_plaintext.c_str(), orig_plaintext.length());
7c673cae
FG
254
255 bufferlist plaintext;
11fdf7f2 256 plaintext.append(orig_plaintext.c_str(), orig_plaintext.length());
7c673cae
FG
257
258 for (int i=0; i<10000; i++) {
259 bufferlist cipher;
260 {
261 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
262
263 std::string error;
264 CryptoKeyHandler *kh = h->get_key_handler(secret, error);
265 int r = kh->encrypt(plaintext, cipher, &error);
266 ASSERT_EQ(r, 0);
267 ASSERT_EQ(error, "");
268
269 delete kh;
270 }
271 plaintext.clear();
272
273 {
274 CryptoHandler *h = g_ceph_context->get_crypto_handler(CEPH_CRYPTO_AES);
275 std::string error;
276 CryptoKeyHandler *ckh = h->get_key_handler(secret, error);
277 int r = ckh->decrypt(cipher, plaintext, &error);
278 ASSERT_EQ(r, 0);
279 ASSERT_EQ(error, "");
280
281 delete ckh;
282 }
283 }
284
11fdf7f2
TL
285 bufferlist orig;
286 orig.append(orig_plaintext);
287 ASSERT_EQ(orig, plaintext);
7c673cae
FG
288}
289
11fdf7f2
TL
290TEST(AES, Loop) {
291 aes_loop(256);
292}
293
294// These magics reflects Cephx's signature size. Please consult
295// CephxSessionHandler::_calc_signature() for more details.
296TEST(AES, Loop_29) {
297 aes_loop(29);
298}
299
300TEST(AES, Loop_32) {
301 aes_loop(32);
302}
303
304void aes_loopkey(const std::size_t text_size) {
305 CryptoRandom random;
7c673cae 306 bufferptr k(16);
11fdf7f2 307 random.get_bytes(k.c_str(), k.length());
7c673cae
FG
308 CryptoKey key(CEPH_CRYPTO_AES, ceph_clock_now(), k);
309
310 bufferlist data;
11fdf7f2
TL
311 bufferptr r(text_size);
312 random.get_bytes(r.c_str(), r.length());
7c673cae
FG
313 data.append(r);
314
315 utime_t start = ceph_clock_now();
316 int n = 100000;
317
318 for (int i=0; i<n; ++i) {
319 bufferlist encoded;
320 string error;
321 int r = key.encrypt(g_ceph_context, data, encoded, &error);
322 ASSERT_EQ(r, 0);
323 }
324
325 utime_t end = ceph_clock_now();
326 utime_t dur = end - start;
327 cout << n << " encoded in " << dur << std::endl;
328}
11fdf7f2
TL
329
330TEST(AES, LoopKey) {
331 aes_loopkey(128);
332}
333
334// These magics reflects Cephx's signature size. Please consult
335// CephxSessionHandler::_calc_signature() for more details.
336TEST(AES, LoopKey_29) {
337 aes_loopkey(29);
338}
339
340TEST(AES, LoopKey_32) {
341 aes_loopkey(32);
342}