Line data Source code
1 : /*
2 : Unit tests for the encrypted secrets code in encrypted_secrets.c
3 :
4 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <stdarg.h>
21 : #include <stddef.h>
22 : #include <setjmp.h>
23 : #include <unistd.h>
24 : #include <cmocka.h>
25 :
26 : int ldb_encrypted_secrets_module_init(const char *version);
27 : #define TEST_ENCRYPTED_SECRETS
28 : #include "../encrypted_secrets.c"
29 :
30 : struct ldbtest_ctx {
31 : struct tevent_context *ev;
32 : struct ldb_context *ldb;
33 : struct ldb_module *module;
34 :
35 : const char *dbfile;
36 : const char *lockfile; /* lockfile is separate */
37 : const char *keyfile;
38 :
39 : const char *dbpath;
40 : };
41 :
42 : /* -------------------------------------------------------------------------- */
43 : /*
44 : * Replace the dsdb helper routines used by the operational_init function
45 : *
46 : */
47 24 : int dsdb_module_search_dn(
48 : struct ldb_module *module,
49 : TALLOC_CTX *mem_ctx,
50 : struct ldb_result **_res,
51 : struct ldb_dn *basedn,
52 : const char * const *attrs,
53 : uint32_t dsdb_flags,
54 : struct ldb_request *parent)
55 : {
56 24 : struct ldb_context *ldb = ldb_module_get_ctx(module);
57 24 : struct ldb_message *msg = ldb_msg_new(ldb);
58 24 : struct ldb_result *res = talloc_zero(mem_ctx, struct ldb_result);
59 :
60 24 : msg->dn = ldb_dn_new(msg, ldb, "@SAMBA_DSDB");
61 24 : ldb_msg_add_string(
62 : msg,
63 : SAMBA_REQUIRED_FEATURES_ATTR,
64 : SAMBA_ENCRYPTED_SECRETS_FEATURE);
65 :
66 24 : res->msgs = talloc_array(mem_ctx, struct ldb_message*, 1);
67 24 : res->msgs[0] = msg;
68 24 : *_res = res;
69 24 : return LDB_SUCCESS;
70 : }
71 :
72 0 : int dsdb_module_reference_dn(
73 : struct ldb_module *module,
74 : TALLOC_CTX *mem_ctx,
75 : struct ldb_dn *base,
76 : const char *attribute,
77 : struct ldb_dn **dn,
78 : struct ldb_request *parent)
79 : {
80 0 : return LDB_SUCCESS;
81 : }
82 : /* -------------------------------------------------------------------------- */
83 :
84 52 : static void unlink_old_db(struct ldbtest_ctx *test_ctx)
85 : {
86 52 : int ret;
87 :
88 52 : errno = 0;
89 52 : ret = unlink(test_ctx->lockfile);
90 52 : if (ret == -1 && errno != ENOENT) {
91 0 : fail();
92 : }
93 :
94 52 : errno = 0;
95 52 : ret = unlink(test_ctx->dbfile);
96 52 : if (ret == -1 && errno != ENOENT) {
97 0 : fail();
98 : }
99 :
100 52 : errno = 0;
101 52 : ret = unlink(test_ctx->keyfile);
102 52 : if (ret == -1 && errno != ENOENT) {
103 0 : fail();
104 : }
105 52 : }
106 :
107 22 : static void write_key(void **state, DATA_BLOB key) {
108 :
109 22 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
110 : struct ldbtest_ctx);
111 22 : FILE *fp = NULL;
112 22 : int written = 0;
113 :
114 22 : fp = fopen(test_ctx->keyfile, "wb");
115 22 : assert_non_null(fp);
116 :
117 22 : written = fwrite(key.data, 1, key.length, fp);
118 22 : assert_int_equal(written, key.length);
119 22 : fclose(fp);
120 22 : }
121 :
122 : static const struct ldb_module_ops eol_ops = {
123 : .name = "eol",
124 : .search = NULL,
125 : .add = NULL,
126 : .modify = NULL,
127 : .del = NULL,
128 : .rename = NULL,
129 : .init_context = NULL
130 : };
131 :
132 26 : static int setup(void **state)
133 : {
134 26 : struct ldbtest_ctx *test_ctx = NULL;
135 26 : struct ldb_module *eol = NULL;
136 26 : int rc;
137 :
138 26 : test_ctx = talloc_zero(NULL, struct ldbtest_ctx);
139 26 : assert_non_null(test_ctx);
140 :
141 26 : test_ctx->ev = tevent_context_init(test_ctx);
142 26 : assert_non_null(test_ctx->ev);
143 :
144 26 : test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
145 26 : assert_non_null(test_ctx->ldb);
146 :
147 :
148 :
149 26 : test_ctx->module = ldb_module_new(
150 : test_ctx,
151 : test_ctx->ldb,
152 : "encrypted_secrets",
153 : &ldb_encrypted_secrets_module_ops);
154 26 : assert_non_null(test_ctx->module);
155 26 : eol = ldb_module_new(test_ctx, test_ctx->ldb, "eol", &eol_ops);
156 26 : assert_non_null(eol);
157 26 : ldb_module_set_next(test_ctx->module, eol);
158 :
159 26 : test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb");
160 26 : assert_non_null(test_ctx->dbfile);
161 :
162 26 : test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
163 : test_ctx->dbfile);
164 26 : assert_non_null(test_ctx->lockfile);
165 :
166 26 : test_ctx->keyfile = talloc_strdup(test_ctx, SECRETS_KEY_FILE);
167 26 : assert_non_null(test_ctx->keyfile);
168 :
169 26 : test_ctx->dbpath = talloc_asprintf(test_ctx,
170 : TEST_BE"://%s", test_ctx->dbfile);
171 26 : assert_non_null(test_ctx->dbpath);
172 :
173 26 : unlink_old_db(test_ctx);
174 :
175 26 : rc = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
176 26 : assert_int_equal(rc, 0);
177 26 : *state = test_ctx;
178 26 : return 0;
179 : }
180 :
181 16 : static int setup_with_key(void **state)
182 : {
183 16 : struct ldbtest_ctx *test_ctx = NULL;
184 16 : DATA_BLOB key = data_blob_null;
185 16 : uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
186 : 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
187 16 : int rc;
188 :
189 16 : setup(state);
190 16 : key.data = key_data;
191 16 : key.length = sizeof(key_data);
192 :
193 16 : write_key(state, key);
194 :
195 16 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
196 : {
197 16 : struct ldb_message *msg = ldb_msg_new(test_ctx->ldb);
198 16 : msg->dn = ldb_dn_new(msg, test_ctx->ldb, "@SAMBA_DSDB");
199 16 : ldb_msg_add_string(
200 : msg,
201 : SAMBA_REQUIRED_FEATURES_ATTR,
202 : SAMBA_ENCRYPTED_SECRETS_FEATURE);
203 16 : ldb_add(test_ctx->ldb, msg);
204 : }
205 :
206 16 : rc = es_init(test_ctx->module);
207 16 : assert_int_equal(rc, LDB_SUCCESS);
208 :
209 16 : return 0;
210 : }
211 :
212 26 : static int teardown(void **state)
213 : {
214 26 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
215 : struct ldbtest_ctx);
216 :
217 26 : unlink_old_db(test_ctx);
218 26 : talloc_free(test_ctx);
219 26 : return 0;
220 : }
221 : /*
222 : * No key file present.
223 : *
224 : * The key should be empty and encrypt_secrets should be false.
225 : */
226 2 : static void test_no_key_file(void **state)
227 : {
228 2 : struct ldbtest_ctx *test_ctx =
229 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
230 2 : struct es_data *data = NULL;
231 :
232 2 : int rc;
233 :
234 2 : rc = es_init(test_ctx->module);
235 2 : assert_int_equal(rc, LDB_SUCCESS);
236 :
237 2 : data = talloc_get_type(ldb_module_get_private(test_ctx->module),
238 : struct es_data);
239 :
240 2 : assert_false(data->encrypt_secrets);
241 2 : assert_int_equal(0, data->keys[0].length);
242 :
243 2 : }
244 :
245 : /*
246 : * Key file present.
247 : *
248 : * The key should be loaded and encrypt secrets should be true;
249 : */
250 2 : static void test_key_file(void **state)
251 : {
252 2 : struct ldbtest_ctx *test_ctx =
253 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
254 2 : struct es_data *data = NULL;
255 2 : int rc;
256 2 : DATA_BLOB key = data_blob_null;
257 2 : uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
258 : 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
259 :
260 2 : key.data = key_data;
261 2 : key.length = sizeof(key_data);
262 :
263 2 : write_key(state, key);
264 :
265 :
266 2 : rc = es_init(test_ctx->module);
267 2 : assert_int_equal(rc, LDB_SUCCESS);
268 :
269 2 : data = talloc_get_type(ldb_module_get_private(test_ctx->module),
270 : struct es_data);
271 :
272 2 : assert_true(data->encrypt_secrets);
273 2 : assert_int_equal(16, data->keys[0].length);
274 2 : assert_int_equal(0, data_blob_cmp(&key, &data->keys[0]));
275 :
276 2 : }
277 :
278 : /*
279 : * Key file present, short key.
280 : *
281 : * The key should be not be loaded and an error returned.
282 : */
283 2 : static void test_key_file_short_key(void **state)
284 : {
285 2 : struct ldbtest_ctx *test_ctx =
286 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
287 2 : int rc;
288 2 : DATA_BLOB key = data_blob_null;
289 2 : uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
290 : 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e};
291 :
292 2 : key.data = key_data;
293 2 : key.length = sizeof(key_data);
294 :
295 2 : write_key(state, key);
296 :
297 :
298 2 : rc = es_init(test_ctx->module);
299 2 : assert_int_equal(rc, LDB_ERR_OPERATIONS_ERROR);
300 2 : }
301 :
302 : /*
303 : * Key file present, long key.
304 : *
305 : * Only the first 16 bytes of the key should be loaded.
306 : */
307 2 : static void test_key_file_long_key(void **state)
308 : {
309 2 : struct ldbtest_ctx *test_ctx =
310 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
311 2 : struct es_data *data = NULL;
312 2 : int rc;
313 2 : DATA_BLOB key = data_blob_null;
314 2 : uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
315 : 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf,
316 : 0x10};
317 :
318 2 : key.data = key_data;
319 2 : key.length = sizeof(key_data);
320 :
321 2 : write_key(state, key);
322 :
323 2 : rc = es_init(test_ctx->module);
324 2 : assert_int_equal(rc, LDB_SUCCESS);
325 :
326 2 : data = talloc_get_type(ldb_module_get_private(test_ctx->module),
327 : struct es_data);
328 :
329 2 : assert_true(data->encrypt_secrets);
330 2 : assert_int_equal(16, data->keys[0].length);
331 :
332 : /*
333 : * Should have only read the first 16 bytes of the written key
334 : */
335 2 : key.length = 16;
336 2 : assert_int_equal(0, data_blob_cmp(&key, &data->keys[0]));
337 2 : }
338 :
339 : /*
340 : * Test gnutls_encryption and decryption.
341 : */
342 2 : static void test_gnutls_value_decryption(void **state)
343 : {
344 2 : struct ldbtest_ctx *test_ctx =
345 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
346 2 : const struct ldb_val plain_text =
347 2 : data_blob_string_const("A text value");
348 2 : unsigned char iv_data[] = {
349 : 0xe7, 0xa3, 0x85, 0x17, 0x45, 0x73, 0xf4, 0x25,
350 : 0xa5, 0x56, 0xde, 0x4c,
351 : };
352 2 : unsigned char encrypted_data[] = {
353 : 0xac, 0x13, 0x86, 0x94, 0x3b, 0xed, 0xf2, 0x51,
354 : 0xec, 0x85, 0x4d, 0x00, 0x37, 0x81, 0x46, 0x15,
355 : 0x42, 0x13, 0xb1, 0x69, 0x49, 0x10, 0xe7, 0x9e,
356 : 0x15, 0xbd, 0x95, 0x75, 0x6b, 0x0c, 0xc0, 0xa4,
357 : };
358 2 : struct EncryptedSecret es = {
359 : .iv = {
360 : .data = iv_data,
361 : .length = sizeof(iv_data),
362 : },
363 : .header = {
364 : .magic = ENCRYPTED_SECRET_MAGIC_VALUE,
365 : .version = SECRET_ATTRIBUTE_VERSION,
366 : .algorithm = ENC_SECRET_AES_128_AEAD,
367 : },
368 : .encrypted = {
369 : .data = encrypted_data,
370 : .length = sizeof(encrypted_data),
371 : }
372 : };
373 2 : unsigned char es_keys_blob[] = {
374 : 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
375 : 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
376 : };
377 2 : struct es_data data = {
378 : .encrypt_secrets = true,
379 : .keys[0] = {
380 : .data = es_keys_blob,
381 : .length = sizeof(es_keys_blob),
382 : },
383 : .encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM,
384 : };
385 2 : struct PlaintextSecret *decrypted =
386 2 : talloc_zero(test_ctx, struct PlaintextSecret);
387 2 : int err = LDB_SUCCESS;
388 :
389 2 : gnutls_decrypt_aead(&err,
390 : test_ctx,
391 : test_ctx->ldb,
392 : &es,
393 : decrypted,
394 : &data);
395 2 : assert_int_equal(LDB_SUCCESS, err);
396 2 : assert_int_equal(plain_text.length, decrypted->cleartext.length);
397 2 : assert_int_equal(0, data_blob_cmp(&decrypted->cleartext, &plain_text));
398 2 : }
399 :
400 : /*
401 : * Test gnutls_encryption and decryption.
402 : */
403 2 : static void test_gnutls_value_encryption(void **state)
404 : {
405 2 : struct ldbtest_ctx *test_ctx =
406 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
407 2 : struct ldb_val plain_text = data_blob_null;
408 2 : struct ldb_val cipher_text = data_blob_null;
409 2 : struct EncryptedSecret es;
410 :
411 2 : struct es_data *data = talloc_get_type(
412 : ldb_module_get_private(test_ctx->module),
413 : struct es_data);
414 2 : int err = LDB_SUCCESS;
415 2 : int rc;
416 :
417 2 : plain_text = data_blob_string_const("A text value");
418 2 : cipher_text = gnutls_encrypt_aead(
419 : &err,
420 : test_ctx,
421 : test_ctx->ldb,
422 : plain_text,
423 : data);
424 2 : assert_int_equal(LDB_SUCCESS, err);
425 :
426 2 : rc = ndr_pull_struct_blob(
427 : &cipher_text,
428 : test_ctx,
429 : &es,
430 : (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
431 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
432 4 : assert_true(check_header(&es));
433 :
434 : {
435 2 : struct PlaintextSecret *decrypted =
436 2 : talloc_zero(test_ctx, struct PlaintextSecret);
437 2 : gnutls_decrypt_aead(
438 : &err,
439 : test_ctx,
440 : test_ctx->ldb,
441 : &es,
442 : decrypted,
443 : data);
444 2 : assert_int_equal(LDB_SUCCESS, err);
445 2 : assert_int_equal(
446 : plain_text.length,
447 : decrypted->cleartext.length);
448 2 : assert_int_equal(0,
449 : data_blob_cmp(
450 : &decrypted->cleartext,
451 : &plain_text));
452 : }
453 2 : }
454 :
455 2 : static void test_gnutls_altered_header(void **state)
456 : {
457 2 : struct ldbtest_ctx *test_ctx =
458 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
459 2 : struct ldb_val plain_text = data_blob_null;
460 2 : struct ldb_val cipher_text = data_blob_null;
461 2 : struct EncryptedSecret es;
462 :
463 2 : struct es_data *data = talloc_get_type(
464 : ldb_module_get_private(test_ctx->module),
465 : struct es_data);
466 2 : int err = LDB_SUCCESS;
467 2 : int rc;
468 :
469 2 : plain_text = data_blob_string_const("A text value");
470 2 : cipher_text = gnutls_encrypt_aead(
471 : &err,
472 : test_ctx,
473 : test_ctx->ldb,
474 : plain_text,
475 : data);
476 2 : assert_int_equal(LDB_SUCCESS, err);
477 :
478 2 : rc = ndr_pull_struct_blob(
479 : &cipher_text,
480 : test_ctx,
481 : &es,
482 : (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
483 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
484 4 : assert_true(check_header(&es));
485 :
486 : {
487 2 : struct PlaintextSecret *decrypted =
488 2 : talloc_zero(test_ctx, struct PlaintextSecret);
489 2 : gnutls_decrypt_aead(
490 : &err,
491 : test_ctx,
492 : test_ctx->ldb,
493 : &es,
494 : decrypted,
495 : data);
496 2 : assert_int_equal(LDB_SUCCESS, err);
497 2 : assert_int_equal(
498 : plain_text.length,
499 : decrypted->cleartext.length);
500 2 : assert_int_equal(0,
501 : data_blob_cmp(
502 : &decrypted->cleartext,
503 : &plain_text));
504 : }
505 2 : es.header.flags = es.header.flags ^ 0xffffffff;
506 : {
507 2 : struct PlaintextSecret *decrypted =
508 2 : talloc_zero(test_ctx, struct PlaintextSecret);
509 2 : gnutls_decrypt_aead(
510 : &err,
511 : test_ctx,
512 : test_ctx->ldb,
513 : &es,
514 : decrypted,
515 : data);
516 2 : assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
517 : }
518 2 : }
519 :
520 2 : static void test_gnutls_altered_data(void **state)
521 : {
522 2 : struct ldbtest_ctx *test_ctx =
523 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
524 2 : struct ldb_val plain_text = data_blob_null;
525 2 : struct ldb_val cipher_text = data_blob_null;
526 2 : struct EncryptedSecret es;
527 :
528 2 : struct es_data *data = talloc_get_type(
529 : ldb_module_get_private(test_ctx->module),
530 : struct es_data);
531 2 : int err = LDB_SUCCESS;
532 2 : int rc;
533 :
534 2 : plain_text = data_blob_string_const("A text value");
535 2 : cipher_text = gnutls_encrypt_aead(
536 : &err,
537 : test_ctx,
538 : test_ctx->ldb,
539 : plain_text,
540 : data);
541 2 : assert_int_equal(LDB_SUCCESS, err);
542 :
543 2 : rc = ndr_pull_struct_blob(
544 : &cipher_text,
545 : test_ctx,
546 : &es,
547 : (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
548 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
549 4 : assert_true(check_header(&es));
550 :
551 : {
552 2 : struct PlaintextSecret *decrypted =
553 2 : talloc_zero(test_ctx, struct PlaintextSecret);
554 2 : gnutls_decrypt_aead(
555 : &err,
556 : test_ctx,
557 : test_ctx->ldb,
558 : &es,
559 : decrypted,
560 : data);
561 2 : assert_int_equal(LDB_SUCCESS, err);
562 2 : assert_int_equal(
563 : plain_text.length,
564 : decrypted->cleartext.length);
565 2 : assert_int_equal(0,
566 : data_blob_cmp(
567 : &decrypted->cleartext,
568 : &plain_text));
569 : }
570 2 : es.encrypted.data[0] = es.encrypted.data[0] ^ 0xff;
571 : {
572 2 : struct PlaintextSecret *decrypted =
573 2 : talloc_zero(test_ctx, struct PlaintextSecret);
574 2 : gnutls_decrypt_aead(
575 : &err,
576 : test_ctx,
577 : test_ctx->ldb,
578 : &es,
579 : decrypted,
580 : data);
581 2 : assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
582 : }
583 2 : }
584 :
585 2 : static void test_gnutls_altered_iv(void **state)
586 : {
587 2 : struct ldbtest_ctx *test_ctx =
588 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
589 2 : struct ldb_val plain_text = data_blob_null;
590 2 : struct ldb_val cipher_text = data_blob_null;
591 2 : struct EncryptedSecret es;
592 :
593 2 : struct es_data *data = talloc_get_type(
594 : ldb_module_get_private(test_ctx->module),
595 : struct es_data);
596 2 : int err = LDB_SUCCESS;
597 2 : int rc;
598 :
599 2 : plain_text = data_blob_string_const("A text value");
600 2 : cipher_text = gnutls_encrypt_aead(
601 : &err,
602 : test_ctx,
603 : test_ctx->ldb,
604 : plain_text,
605 : data);
606 2 : assert_int_equal(LDB_SUCCESS, err);
607 :
608 2 : rc = ndr_pull_struct_blob(
609 : &cipher_text,
610 : test_ctx,
611 : &es,
612 : (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
613 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
614 4 : assert_true(check_header(&es));
615 :
616 : {
617 2 : struct PlaintextSecret *decrypted =
618 2 : talloc_zero(test_ctx, struct PlaintextSecret);
619 2 : gnutls_decrypt_aead(
620 : &err,
621 : test_ctx,
622 : test_ctx->ldb,
623 : &es,
624 : decrypted,
625 : data);
626 2 : assert_int_equal(LDB_SUCCESS, err);
627 2 : assert_int_equal(
628 : plain_text.length,
629 : decrypted->cleartext.length);
630 2 : assert_int_equal(0,
631 : data_blob_cmp(
632 : &decrypted->cleartext,
633 : &plain_text));
634 : }
635 2 : es.iv.data[0] = es.iv.data[0] ^ 0xff;
636 : {
637 2 : struct PlaintextSecret *decrypted =
638 2 : talloc_zero(test_ctx, struct PlaintextSecret);
639 2 : gnutls_decrypt_aead(
640 : &err,
641 : test_ctx,
642 : test_ctx->ldb,
643 : &es,
644 : decrypted,
645 : data);
646 2 : assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
647 : }
648 2 : }
649 :
650 : /*
651 : * Test samba encryption and decryption and decryption.
652 : */
653 :
654 : /*
655 : * Test message encryption.
656 : * Test the secret attributes of a message are encrypted and decrypted.
657 : * Test that the non secret attributes are not encrypted.
658 : *
659 : */
660 2 : static void test_message_encryption_decryption(void **state)
661 : {
662 2 : struct ldbtest_ctx *test_ctx =
663 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
664 2 : struct ldb_context *ldb = test_ctx->ldb;
665 2 : const char * const secrets[] = {DSDB_SECRET_ATTRIBUTES};
666 2 : const size_t num_secrets
667 : = (sizeof(secrets)/sizeof(secrets[0]));
668 2 : struct ldb_message *msg = ldb_msg_new(ldb);
669 2 : const struct ldb_message *encrypted_msg = NULL;
670 2 : struct es_data *data = talloc_get_type(
671 : ldb_module_get_private(test_ctx->module),
672 : struct es_data);
673 2 : struct ldb_message_element *el = NULL;
674 2 : int ret = LDB_SUCCESS;
675 2 : size_t i;
676 2 : unsigned int j;
677 :
678 2 : msg->dn = ldb_dn_new(msg, ldb, "dc=test");
679 2 : ldb_msg_add_string(msg, "cmocka_test_name01", "value01");
680 32 : for (i=0; i < num_secrets; i++) {
681 28 : ldb_msg_add_string(
682 : msg,
683 : secrets[i],
684 28 : secrets[i]);
685 : }
686 2 : ldb_msg_add_string(msg, "cmocka_test_name02", "value02");
687 :
688 2 : encrypted_msg = encrypt_secret_attributes(
689 : &ret,
690 : test_ctx,
691 : test_ctx->ldb,
692 : msg,
693 : data);
694 2 : assert_int_equal(LDB_SUCCESS, ret);
695 :
696 : /*
697 : * Check that all the secret attributes have been encrypted
698 : *
699 : */
700 32 : for (i=0; i < num_secrets; i++) {
701 28 : el = ldb_msg_find_element(encrypted_msg, secrets[i]);
702 28 : assert_non_null(el);
703 84 : for (j = 0; j < el->num_values; j++) {
704 28 : int rc = LDB_SUCCESS;
705 56 : struct ldb_val dc = decrypt_value(
706 : &rc,
707 : test_ctx,
708 : test_ctx->ldb,
709 28 : el->values[j],
710 : data);
711 28 : assert_int_equal(LDB_SUCCESS, rc);
712 28 : assert_memory_equal(
713 : secrets[i],
714 : dc.data,
715 : dc.length);
716 28 : TALLOC_FREE(dc.data);
717 : }
718 : }
719 :
720 : /*
721 : * Check that the normal attributes have not been encrypted
722 : */
723 2 : el = ldb_msg_find_element(encrypted_msg, "cmocka_test_name01");
724 2 : assert_non_null(el);
725 2 : assert_memory_equal(
726 : "value01",
727 : el->values[0].data,
728 : el->values[0].length);
729 :
730 2 : el = ldb_msg_find_element(encrypted_msg, "cmocka_test_name02");
731 2 : assert_non_null(el);
732 2 : assert_memory_equal(
733 : "value02",
734 : el->values[0].data,
735 : el->values[0].length);
736 :
737 : /*
738 : * Now decrypt the message
739 : */
740 2 : ret = decrypt_secret_attributes(test_ctx->ldb,
741 : discard_const(encrypted_msg),
742 : data);
743 2 : assert_int_equal(LDB_SUCCESS, ret);
744 :
745 : /*
746 : * Check that all the secret attributes have been decrypted
747 : */
748 32 : for (i=0; i < num_secrets; i++) {
749 28 : el = ldb_msg_find_element(encrypted_msg, secrets[i]);
750 28 : assert_non_null(el);
751 84 : for (j = 0; j < el->num_values; j++) {
752 28 : assert_memory_equal(
753 : secrets[i],
754 : el->values[j].data,
755 : el->values[j].length);
756 : }
757 : }
758 :
759 : /*
760 : * Check that the normal attributes are intact
761 : */
762 2 : el = ldb_msg_find_element(msg, "cmocka_test_name01");
763 2 : assert_non_null(el);
764 2 : assert_memory_equal(
765 : "value01",
766 : el->values[0].data,
767 : el->values[0].length);
768 :
769 2 : el = ldb_msg_find_element(msg, "cmocka_test_name02");
770 2 : assert_non_null(el);
771 2 : assert_memory_equal(
772 : "value02",
773 : el->values[0].data,
774 : el->values[0].length);
775 :
776 2 : }
777 :
778 2 : static void test_check_header(void **state)
779 : {
780 2 : struct ldbtest_ctx *test_ctx =
781 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
782 :
783 2 : struct ldb_val enc = data_blob_null;
784 2 : struct EncryptedSecret *es = NULL;
785 2 : int rc;
786 :
787 : /*
788 : * Valid EncryptedSecret
789 : */
790 2 : es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
791 2 : rc = ndr_push_struct_blob(
792 : &enc,
793 : test_ctx,
794 : es,
795 : (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
796 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
797 4 : assert_true(check_header(es));
798 2 : TALLOC_FREE(enc.data);
799 2 : TALLOC_FREE(es);
800 :
801 : /*
802 : * invalid magic value
803 : */
804 2 : es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
805 2 : es->header.magic = 0xca5cadee;
806 2 : rc = ndr_push_struct_blob(
807 : &enc,
808 : test_ctx,
809 : es,
810 : (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
811 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
812 2 : assert_false(check_header(es));
813 2 : TALLOC_FREE(enc.data);
814 2 : TALLOC_FREE(es);
815 :
816 : /*
817 : * invalid version
818 : */
819 2 : es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
820 2 : es->header.version = SECRET_ATTRIBUTE_VERSION + 1;
821 2 : rc = ndr_push_struct_blob(
822 : &enc,
823 : test_ctx,
824 : es,
825 : (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
826 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
827 4 : assert_false(check_header(es));
828 2 : TALLOC_FREE(enc.data);
829 2 : TALLOC_FREE(es);
830 :
831 : /*
832 : * invalid algorithm
833 : */
834 2 : es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
835 2 : es->header.algorithm = SECRET_ENCRYPTION_ALGORITHM + 1;
836 2 : rc = ndr_push_struct_blob(
837 : &enc,
838 : test_ctx,
839 : es,
840 : (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
841 2 : assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
842 4 : assert_false(check_header(es));
843 2 : TALLOC_FREE(enc.data);
844 2 : TALLOC_FREE(es);
845 2 : }
846 :
847 : /*
848 : * Attempt to decrypt a message containing an unencrypted secret attribute
849 : * this should fail
850 : */
851 2 : static void test_unencrypted_secret(void **state)
852 : {
853 2 : struct ldbtest_ctx *test_ctx =
854 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
855 2 : struct ldb_context *ldb = test_ctx->ldb;
856 2 : struct ldb_message *msg = ldb_msg_new(ldb);
857 2 : struct es_data *data = talloc_get_type(
858 : ldb_module_get_private(test_ctx->module),
859 : struct es_data);
860 2 : int ret = LDB_SUCCESS;
861 :
862 2 : msg->dn = ldb_dn_new(msg, ldb, "dc=test");
863 2 : ldb_msg_add_string(msg, "unicodePwd", "value01");
864 :
865 2 : ret = decrypt_secret_attributes(test_ctx->ldb, msg, data);
866 2 : assert_int_equal(LDB_ERR_OPERATIONS_ERROR, ret);
867 2 : }
868 :
869 : /*
870 : * Test full decryption of a static value with static key
871 : */
872 2 : static void test_record_decryption(void **state)
873 : {
874 2 : struct ldbtest_ctx *test_ctx =
875 2 : talloc_get_type_abort(*state, struct ldbtest_ctx);
876 2 : unsigned char plain_data[] = {
877 : 0xe6, 0xa6, 0xb8, 0xff, 0xdf, 0x06, 0x6c, 0xe3,
878 : 0xea, 0xd0, 0x94, 0xbb, 0x79, 0xbd, 0x0a, 0x24
879 : };
880 2 : unsigned char encrypted_data[] = {
881 : 0x0c, 0x00, 0x00, 0x00, 0x33, 0x91, 0x74, 0x25,
882 : 0x26, 0xcc, 0x0b, 0x8c, 0x21, 0xc1, 0x13, 0xe2,
883 : 0xed, 0xad, 0x5c, 0xca, 0x01, 0x00, 0x00, 0x00,
884 : 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 : 0x1a, 0xdc, 0xc9, 0x11, 0x08, 0xca, 0x2c, 0xfb,
886 : 0xc8, 0x32, 0x6b, 0x1b, 0x25, 0x7f, 0x52, 0xbb,
887 : 0xae, 0x9b, 0x88, 0x52, 0xb0, 0x18, 0x6d, 0x9d,
888 : 0x9b, 0xdd, 0xcd, 0x1b, 0x5f, 0x4a, 0x5c, 0x29,
889 : 0xca, 0x0b, 0x36, 0xaa
890 : };
891 2 : struct ldb_val cipher_text
892 2 : = data_blob_const(encrypted_data,
893 : sizeof(encrypted_data));
894 2 : unsigned char es_keys_blob[] = {
895 : 0x1d, 0xae, 0xf5, 0xaa, 0xa3, 0x85, 0x0d, 0x0a,
896 : 0x8c, 0x24, 0x5c, 0x4c, 0xa7, 0x0f, 0x81, 0x79
897 : };
898 2 : struct es_data data = {
899 : .encrypt_secrets = true,
900 : .keys[0] = {
901 : .data = es_keys_blob,
902 : .length = sizeof(es_keys_blob),
903 : },
904 : .encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM,
905 : };
906 2 : int err = LDB_SUCCESS;
907 2 : struct ldb_val dec = decrypt_value(&err, test_ctx, test_ctx->ldb, cipher_text,
908 : &data);
909 2 : assert_int_equal(LDB_SUCCESS, err);
910 2 : assert_int_equal(sizeof(plain_data), dec.length);
911 2 : assert_memory_equal(dec.data, plain_data, sizeof(plain_data));
912 2 : }
913 :
914 :
915 2 : int main(void) {
916 2 : const struct CMUnitTest tests[] = {
917 : cmocka_unit_test_setup_teardown(
918 : test_no_key_file,
919 : setup,
920 : teardown),
921 : cmocka_unit_test_setup_teardown(
922 : test_key_file,
923 : setup,
924 : teardown),
925 : cmocka_unit_test_setup_teardown(
926 : test_key_file_short_key,
927 : setup,
928 : teardown),
929 : cmocka_unit_test_setup_teardown(
930 : test_key_file_long_key,
931 : setup,
932 : teardown),
933 : cmocka_unit_test_setup_teardown(
934 : test_check_header,
935 : setup,
936 : teardown),
937 : cmocka_unit_test_setup_teardown(
938 : test_gnutls_value_decryption,
939 : setup_with_key,
940 : teardown),
941 : cmocka_unit_test_setup_teardown(
942 : test_gnutls_value_encryption,
943 : setup_with_key,
944 : teardown),
945 : cmocka_unit_test_setup_teardown(
946 : test_gnutls_altered_header,
947 : setup_with_key,
948 : teardown),
949 : cmocka_unit_test_setup_teardown(
950 : test_gnutls_altered_data,
951 : setup_with_key,
952 : teardown),
953 : cmocka_unit_test_setup_teardown(
954 : test_gnutls_altered_iv,
955 : setup_with_key,
956 : teardown),
957 : cmocka_unit_test_setup_teardown(
958 : test_message_encryption_decryption,
959 : setup_with_key,
960 : teardown),
961 : cmocka_unit_test_setup_teardown(
962 : test_unencrypted_secret,
963 : setup_with_key,
964 : teardown),
965 : cmocka_unit_test_setup_teardown(
966 : test_record_decryption,
967 : setup_with_key,
968 : teardown),
969 : };
970 :
971 2 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
972 2 : return cmocka_run_group_tests(tests, NULL, NULL);
973 : }
|