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