dsdb/encrypted_secrets: remove dependency to libnettle and use our own aes_gcm_128_*()
[metze/samba/wip.git] / source4 / dsdb / samdb / ldb_modules / tests / test_encrypted_secrets.c
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 #define TEST_BE "tdb"
31 struct ldbtest_ctx {
32         struct tevent_context *ev;
33         struct ldb_context *ldb;
34         struct ldb_module *module;
35
36         const char *dbfile;
37         const char *lockfile;   /* lockfile is separate */
38         const char *keyfile;
39
40         const char *dbpath;
41 };
42
43 /* -------------------------------------------------------------------------- */
44 /*
45  * Replace the dsdb helper routines used by the operational_init function
46  *
47  */
48 int dsdb_module_search_dn(
49         struct ldb_module *module,
50         TALLOC_CTX *mem_ctx,
51         struct ldb_result **_res,
52         struct ldb_dn *basedn,
53         const char * const *attrs,
54         uint32_t dsdb_flags,
55         struct ldb_request *parent)
56 {
57         struct ldb_context *ldb = ldb_module_get_ctx(module);
58         struct ldb_message *msg = ldb_msg_new(ldb);
59         struct ldb_result  *res = talloc_zero(mem_ctx, struct ldb_result);
60
61         msg->dn = ldb_dn_new(msg, ldb, "@SAMBA_DSDB");
62         ldb_msg_add_string(
63                 msg,
64                 SAMBA_REQUIRED_FEATURES_ATTR,
65                 SAMBA_ENCRYPTED_SECRETS_FEATURE);
66
67         res->msgs = talloc_array(mem_ctx, struct ldb_message*, 1);
68         res->msgs[0] = msg;
69         *_res = res;
70         return LDB_SUCCESS;
71 }
72
73 int dsdb_module_reference_dn(
74         struct ldb_module *module,
75         TALLOC_CTX *mem_ctx,
76         struct ldb_dn *base,
77         const char *attribute,
78         struct ldb_dn **dn,
79         struct ldb_request *parent)
80 {
81         return LDB_SUCCESS;
82 }
83 /* -------------------------------------------------------------------------- */
84
85 static void unlink_old_db(struct ldbtest_ctx *test_ctx)
86 {
87         int ret;
88
89         errno = 0;
90         ret = unlink(test_ctx->lockfile);
91         if (ret == -1 && errno != ENOENT) {
92                 fail();
93         }
94
95         errno = 0;
96         ret = unlink(test_ctx->dbfile);
97         if (ret == -1 && errno != ENOENT) {
98                 fail();
99         }
100
101         errno = 0;
102         ret = unlink(test_ctx->keyfile);
103         if (ret == -1 && errno != ENOENT) {
104                 fail();
105         }
106 }
107
108 static void write_key(void **state, DATA_BLOB key) {
109
110         struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
111                                                         struct ldbtest_ctx);
112         FILE *fp = NULL;
113         int written = 0;
114
115         fp = fopen(test_ctx->keyfile, "wb");
116         assert_non_null(fp);
117
118         written = fwrite(key.data, 1, key.length, fp);
119         assert_int_equal(written, key.length);
120         fclose(fp);
121 }
122
123 static const struct ldb_module_ops eol_ops = {
124         .name              = "eol",
125         .search            = NULL,
126         .add               = NULL,
127         .modify            = NULL,
128         .del               = NULL,
129         .rename            = NULL,
130         .init_context      = NULL
131 };
132
133 static int setup(void **state)
134 {
135         struct ldbtest_ctx *test_ctx = NULL;
136         struct ldb_module *eol = NULL;
137         int rc;
138
139         test_ctx = talloc_zero(NULL, struct ldbtest_ctx);
140         assert_non_null(test_ctx);
141
142         test_ctx->ev = tevent_context_init(test_ctx);
143         assert_non_null(test_ctx->ev);
144
145         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
146         assert_non_null(test_ctx->ldb);
147
148
149
150         test_ctx->module = ldb_module_new(
151                 test_ctx,
152                 test_ctx->ldb,
153                 "encrypted_secrets",
154                 &ldb_encrypted_secrets_module_ops);
155         assert_non_null(test_ctx->module);
156         eol = ldb_module_new(test_ctx, test_ctx->ldb, "eol", &eol_ops);
157         assert_non_null(eol);
158         ldb_module_set_next(test_ctx->module, eol);
159
160         test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb");
161         assert_non_null(test_ctx->dbfile);
162
163         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
164                                              test_ctx->dbfile);
165         assert_non_null(test_ctx->lockfile);
166
167         test_ctx->keyfile = talloc_strdup(test_ctx, SECRETS_KEY_FILE);
168         assert_non_null(test_ctx->keyfile);
169
170         test_ctx->dbpath = talloc_asprintf(test_ctx,
171                         TEST_BE"://%s", test_ctx->dbfile);
172         assert_non_null(test_ctx->dbpath);
173
174         unlink_old_db(test_ctx);
175
176         rc = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
177         assert_int_equal(rc, 0);
178         *state = test_ctx;
179         return 0;
180 }
181
182 static int setup_with_key(void **state)
183 {
184         struct ldbtest_ctx *test_ctx = NULL;
185         DATA_BLOB key = data_blob_null;
186         uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
187                               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
188         int rc;
189
190         setup(state);
191         key.data   = key_data;
192         key.length = sizeof(key_data);
193
194         write_key(state, key);
195
196         test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
197         {
198                 struct ldb_message *msg = ldb_msg_new(test_ctx->ldb);
199                 msg->dn = ldb_dn_new(msg, test_ctx->ldb, "@SAMBA_DSDB");
200                 ldb_msg_add_string(
201                         msg,
202                         SAMBA_REQUIRED_FEATURES_ATTR,
203                         SAMBA_ENCRYPTED_SECRETS_FEATURE);
204                 ldb_add(test_ctx->ldb, msg);
205         }
206
207         rc = es_init(test_ctx->module);
208         assert_int_equal(rc, LDB_SUCCESS);
209
210         return 0;
211 }
212
213 static int teardown(void **state)
214 {
215         struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
216                                                         struct ldbtest_ctx);
217
218         unlink_old_db(test_ctx);
219         talloc_free(test_ctx);
220         return 0;
221 }
222 /*
223  * No key file present.
224  *
225  * The key should be empty and encrypt_secrets should be false.
226  */
227 static void test_no_key_file(void **state)
228 {
229         struct ldbtest_ctx *test_ctx =
230                 talloc_get_type_abort(*state, struct ldbtest_ctx);
231         struct es_data *data = NULL;
232
233         int rc;
234
235         rc = es_init(test_ctx->module);
236         assert_int_equal(rc, LDB_SUCCESS);
237
238         data = talloc_get_type(ldb_module_get_private(test_ctx->module),
239                                struct es_data);
240
241         assert_false(data->encrypt_secrets);
242         assert_int_equal(0, data->keys[0].length);
243
244 }
245
246 /*
247  * Key file present.
248  *
249  * The key should be loaded and encrypt secrets should be true;
250  */
251 static void test_key_file(void **state)
252 {
253         struct ldbtest_ctx *test_ctx =
254                 talloc_get_type_abort(*state, struct ldbtest_ctx);
255         struct es_data *data = NULL;
256         int rc;
257         DATA_BLOB key = data_blob_null;
258         uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
259                               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
260
261         key.data   = key_data;
262         key.length = sizeof(key_data);
263
264         write_key(state, key);
265
266
267         rc = es_init(test_ctx->module);
268         assert_int_equal(rc, LDB_SUCCESS);
269
270         data = talloc_get_type(ldb_module_get_private(test_ctx->module),
271                                struct es_data);
272
273         assert_true(data->encrypt_secrets);
274         assert_int_equal(16, data->keys[0].length);
275         assert_int_equal(0, data_blob_cmp(&key, &data->keys[0]));
276
277 }
278
279 /*
280  * Key file present, short key.
281  *
282  * The key should be not be loaded and an error returned.
283  */
284 static void test_key_file_short_key(void **state)
285 {
286         struct ldbtest_ctx *test_ctx =
287                 talloc_get_type_abort(*state, struct ldbtest_ctx);
288         int rc;
289         DATA_BLOB key = data_blob_null;
290         uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
291                               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e};
292
293         key.data   = key_data;
294         key.length = sizeof(key_data);
295
296         write_key(state, key);
297
298
299         rc = es_init(test_ctx->module);
300         assert_int_equal(rc, LDB_ERR_OPERATIONS_ERROR);
301 }
302
303 /*
304  * Key file present, long key.
305  *
306  * Only the first 16 bytes of the key should be loaded.
307  */
308 static void test_key_file_long_key(void **state)
309 {
310         struct ldbtest_ctx *test_ctx =
311                 talloc_get_type_abort(*state, struct ldbtest_ctx);
312         struct es_data *data = NULL;
313         int rc;
314         DATA_BLOB key = data_blob_null;
315         uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
316                               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf,
317                               0x10};
318
319         key.data   = key_data;
320         key.length = sizeof(key_data);
321
322         write_key(state, key);
323
324         rc = es_init(test_ctx->module);
325         assert_int_equal(rc, LDB_SUCCESS);
326
327         data = talloc_get_type(ldb_module_get_private(test_ctx->module),
328                                struct es_data);
329
330         assert_true(data->encrypt_secrets);
331         assert_int_equal(16, data->keys[0].length);
332
333         /*
334          * Should have only read the first 16 bytes of the written key
335          */
336         key.length = 16;
337         assert_int_equal(0, data_blob_cmp(&key, &data->keys[0]));
338 }
339
340 #ifdef HAVE_GNUTLS_AEAD
341 /*
342  *  Test gnutls_encryption and decryption.
343  */
344 static void test_gnutls_value_encryption(void **state)
345 {
346         struct ldbtest_ctx *test_ctx =
347                 talloc_get_type_abort(*state, struct ldbtest_ctx);
348         struct ldb_val plain_text = data_blob_null;
349         struct ldb_val cipher_text = data_blob_null;
350         struct EncryptedSecret es;
351
352         struct es_data *data = talloc_get_type(
353                 ldb_module_get_private(test_ctx->module),
354                 struct es_data);
355         int err = LDB_SUCCESS;
356         int rc;
357
358         plain_text = data_blob_string_const("A text value");
359         cipher_text = gnutls_encrypt_aead(
360                         &err,
361                         test_ctx,
362                         test_ctx->ldb,
363                         plain_text,
364                         data);
365         assert_int_equal(LDB_SUCCESS, err);
366
367         rc = ndr_pull_struct_blob(
368                 &cipher_text,
369                 test_ctx,
370                 &es,
371                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
372         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
373         assert_true(check_header(&es));
374
375         {
376                 struct PlaintextSecret *decrypted =
377                         talloc_zero(test_ctx, struct PlaintextSecret);
378                 gnutls_decrypt_aead(
379                         &err,
380                         test_ctx,
381                         test_ctx->ldb,
382                         &es,
383                         decrypted,
384                         data);
385                 assert_int_equal(LDB_SUCCESS, err);
386                 assert_int_equal(
387                         plain_text.length,
388                         decrypted->cleartext.length);
389                 assert_int_equal(0,
390                         data_blob_cmp(
391                                 &decrypted->cleartext,
392                                 &plain_text));
393         }
394
395         {
396                 struct PlaintextSecret *decrypted =
397                         talloc_zero(test_ctx, struct PlaintextSecret);
398                 samba_decrypt_aead(
399                         &err,
400                         test_ctx,
401                         test_ctx->ldb,
402                         &es,
403                         decrypted,
404                         data);
405                 assert_int_equal(LDB_SUCCESS, err);
406                 assert_int_equal(
407                         plain_text.length,
408                         decrypted->cleartext.length);
409                 assert_int_equal(0,
410                         data_blob_cmp(
411                                 &decrypted->cleartext,
412                                 &plain_text));
413         }
414 }
415 #endif /* HAVE_GNUTLS_AEAD */
416
417 #ifdef HAVE_GNUTLS_AEAD
418 static void test_gnutls_altered_header(void **state)
419 {
420         struct ldbtest_ctx *test_ctx =
421                 talloc_get_type_abort(*state, struct ldbtest_ctx);
422         struct ldb_val plain_text = data_blob_null;
423         struct ldb_val cipher_text = data_blob_null;
424         struct EncryptedSecret es;
425
426         struct es_data *data = talloc_get_type(
427                 ldb_module_get_private(test_ctx->module),
428                 struct es_data);
429         int err = LDB_SUCCESS;
430         int rc;
431
432         plain_text = data_blob_string_const("A text value");
433         cipher_text = gnutls_encrypt_aead(
434                         &err,
435                         test_ctx,
436                         test_ctx->ldb,
437                         plain_text,
438                         data);
439         assert_int_equal(LDB_SUCCESS, err);
440
441         rc = ndr_pull_struct_blob(
442                 &cipher_text,
443                 test_ctx,
444                 &es,
445                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
446         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
447         assert_true(check_header(&es));
448
449         {
450                 struct PlaintextSecret *decrypted =
451                         talloc_zero(test_ctx, struct PlaintextSecret);
452                 gnutls_decrypt_aead(
453                         &err,
454                         test_ctx,
455                         test_ctx->ldb,
456                         &es,
457                         decrypted,
458                         data);
459                 assert_int_equal(LDB_SUCCESS, err);
460                 assert_int_equal(
461                         plain_text.length,
462                         decrypted->cleartext.length);
463                 assert_int_equal(0,
464                         data_blob_cmp(
465                                 &decrypted->cleartext,
466                                 &plain_text));
467         }
468         es.header.flags = es.header.flags ^ 0xffffffff;
469         {
470                 struct PlaintextSecret *decrypted =
471                         talloc_zero(test_ctx, struct PlaintextSecret);
472                 gnutls_decrypt_aead(
473                         &err,
474                         test_ctx,
475                         test_ctx->ldb,
476                         &es,
477                         decrypted,
478                         data);
479                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
480         }
481 }
482 #endif /* HAVE_GNUTLS_AEAD */
483
484 #ifdef HAVE_GNUTLS_AEAD
485 static void test_gnutls_altered_data(void **state)
486 {
487         struct ldbtest_ctx *test_ctx =
488                 talloc_get_type_abort(*state, struct ldbtest_ctx);
489         struct ldb_val plain_text = data_blob_null;
490         struct ldb_val cipher_text = data_blob_null;
491         struct EncryptedSecret es;
492
493         struct es_data *data = talloc_get_type(
494                 ldb_module_get_private(test_ctx->module),
495                 struct es_data);
496         int err = LDB_SUCCESS;
497         int rc;
498
499         plain_text = data_blob_string_const("A text value");
500         cipher_text = gnutls_encrypt_aead(
501                         &err,
502                         test_ctx,
503                         test_ctx->ldb,
504                         plain_text,
505                         data);
506         assert_int_equal(LDB_SUCCESS, err);
507
508         rc = ndr_pull_struct_blob(
509                 &cipher_text,
510                 test_ctx,
511                 &es,
512                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
513         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
514         assert_true(check_header(&es));
515
516         {
517                 struct PlaintextSecret *decrypted =
518                         talloc_zero(test_ctx, struct PlaintextSecret);
519                 gnutls_decrypt_aead(
520                         &err,
521                         test_ctx,
522                         test_ctx->ldb,
523                         &es,
524                         decrypted,
525                         data);
526                 assert_int_equal(LDB_SUCCESS, err);
527                 assert_int_equal(
528                         plain_text.length,
529                         decrypted->cleartext.length);
530                 assert_int_equal(0,
531                         data_blob_cmp(
532                                 &decrypted->cleartext,
533                                 &plain_text));
534         }
535         es.encrypted.data[0] = es.encrypted.data[0] ^ 0xff;
536         {
537                 struct PlaintextSecret *decrypted =
538                         talloc_zero(test_ctx, struct PlaintextSecret);
539                 gnutls_decrypt_aead(
540                         &err,
541                         test_ctx,
542                         test_ctx->ldb,
543                         &es,
544                         decrypted,
545                         data);
546                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
547         }
548 }
549 #endif /* HAVE_GNUTLS_AEAD */
550
551 #ifdef HAVE_GNUTLS_AEAD
552 static void test_gnutls_altered_iv(void **state)
553 {
554         struct ldbtest_ctx *test_ctx =
555                 talloc_get_type_abort(*state, struct ldbtest_ctx);
556         struct ldb_val plain_text = data_blob_null;
557         struct ldb_val cipher_text = data_blob_null;
558         struct EncryptedSecret es;
559
560         struct es_data *data = talloc_get_type(
561                 ldb_module_get_private(test_ctx->module),
562                 struct es_data);
563         int err = LDB_SUCCESS;
564         int rc;
565
566         plain_text = data_blob_string_const("A text value");
567         cipher_text = gnutls_encrypt_aead(
568                         &err,
569                         test_ctx,
570                         test_ctx->ldb,
571                         plain_text,
572                         data);
573         assert_int_equal(LDB_SUCCESS, err);
574
575         rc = ndr_pull_struct_blob(
576                 &cipher_text,
577                 test_ctx,
578                 &es,
579                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
580         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
581         assert_true(check_header(&es));
582
583         {
584                 struct PlaintextSecret *decrypted =
585                         talloc_zero(test_ctx, struct PlaintextSecret);
586                 gnutls_decrypt_aead(
587                         &err,
588                         test_ctx,
589                         test_ctx->ldb,
590                         &es,
591                         decrypted,
592                         data);
593                 assert_int_equal(LDB_SUCCESS, err);
594                 assert_int_equal(
595                         plain_text.length,
596                         decrypted->cleartext.length);
597                 assert_int_equal(0,
598                         data_blob_cmp(
599                                 &decrypted->cleartext,
600                                 &plain_text));
601         }
602         es.iv.data[0] = es.iv.data[0] ^ 0xff;
603         {
604                 struct PlaintextSecret *decrypted =
605                         talloc_zero(test_ctx, struct PlaintextSecret);
606                 gnutls_decrypt_aead(
607                         &err,
608                         test_ctx,
609                         test_ctx->ldb,
610                         &es,
611                         decrypted,
612                         data);
613                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
614         }
615 }
616 #endif /* HAVE_GNUTLS_AEAD */
617 /*
618  *  Test samba encryption and decryption and decryption.
619  */
620 static void test_samba_value_encryption(void **state)
621 {
622         struct ldbtest_ctx *test_ctx =
623                 talloc_get_type_abort(*state, struct ldbtest_ctx);
624         struct ldb_val plain_text = data_blob_null;
625         struct ldb_val cipher_text = data_blob_null;
626         struct EncryptedSecret es;
627
628         struct es_data *data = talloc_get_type(
629                 ldb_module_get_private(test_ctx->module),
630                 struct es_data);
631         int err = LDB_SUCCESS;
632         int rc;
633
634         plain_text = data_blob_string_const("A text value");
635         cipher_text = samba_encrypt_aead(
636                         &err,
637                         test_ctx,
638                         test_ctx->ldb,
639                         plain_text,
640                         data);
641         assert_int_equal(LDB_SUCCESS, err);
642
643         rc = ndr_pull_struct_blob(
644                 &cipher_text,
645                 test_ctx,
646                 &es,
647                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
648         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
649         assert_true(check_header(&es));
650
651 #ifdef HAVE_GNUTLS_AEAD
652         {
653                 struct PlaintextSecret *decrypted =
654                         talloc_zero(test_ctx, struct PlaintextSecret);
655                 gnutls_decrypt_aead(
656                         &err,
657                         test_ctx,
658                         test_ctx->ldb,
659                         &es,
660                         decrypted,
661                         data);
662                 assert_int_equal(LDB_SUCCESS, err);
663                 assert_int_equal(
664                         plain_text.length,
665                         decrypted->cleartext.length);
666                 assert_int_equal(0,
667                         data_blob_cmp(
668                                 &decrypted->cleartext,
669                                 &plain_text));
670         }
671 #endif /* HAVE_GNUTLS_AEAD */
672
673
674         {
675                 struct PlaintextSecret *decrypted =
676                         talloc_zero(test_ctx, struct PlaintextSecret);
677                 samba_decrypt_aead(
678                         &err,
679                         test_ctx,
680                         test_ctx->ldb,
681                         &es,
682                         decrypted,
683                         data);
684                 assert_int_equal(LDB_SUCCESS, err);
685                 assert_int_equal(
686                         plain_text.length,
687                         decrypted->cleartext.length);
688                 assert_int_equal(0,
689                         data_blob_cmp(
690                                 &decrypted->cleartext,
691                                 &plain_text));
692         }
693
694 }
695
696 static void test_samba_altered_header(void **state)
697 {
698         struct ldbtest_ctx *test_ctx =
699                 talloc_get_type_abort(*state, struct ldbtest_ctx);
700         struct ldb_val plain_text = data_blob_null;
701         struct ldb_val cipher_text = data_blob_null;
702         struct EncryptedSecret es;
703
704         struct es_data *data = talloc_get_type(
705                 ldb_module_get_private(test_ctx->module),
706                 struct es_data);
707         int err = LDB_SUCCESS;
708         int rc;
709
710         plain_text = data_blob_string_const("A text value");
711         cipher_text = samba_encrypt_aead(
712                         &err,
713                         test_ctx,
714                         test_ctx->ldb,
715                         plain_text,
716                         data);
717         assert_int_equal(LDB_SUCCESS, err);
718
719         rc = ndr_pull_struct_blob(
720                 &cipher_text,
721                 test_ctx,
722                 &es,
723                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
724         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
725         assert_true(check_header(&es));
726
727         {
728                 struct PlaintextSecret *decrypted =
729                         talloc_zero(test_ctx, struct PlaintextSecret);
730                 samba_decrypt_aead(
731                         &err,
732                         test_ctx,
733                         test_ctx->ldb,
734                         &es,
735                         decrypted,
736                         data);
737                 assert_int_equal(LDB_SUCCESS, err);
738                 assert_int_equal(
739                         plain_text.length,
740                         decrypted->cleartext.length);
741                 assert_int_equal(0,
742                         data_blob_cmp(
743                                 &decrypted->cleartext,
744                                 &plain_text));
745         }
746         es.header.flags = es.header.flags ^ 0xffffffff;
747         {
748                 struct PlaintextSecret *decrypted =
749                         talloc_zero(test_ctx, struct PlaintextSecret);
750                 samba_decrypt_aead(
751                         &err,
752                         test_ctx,
753                         test_ctx->ldb,
754                         &es,
755                         decrypted,
756                         data);
757                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
758         }
759 }
760
761 static void test_samba_altered_data(void **state)
762 {
763         struct ldbtest_ctx *test_ctx =
764                 talloc_get_type_abort(*state, struct ldbtest_ctx);
765         struct ldb_val plain_text = data_blob_null;
766         struct ldb_val cipher_text = data_blob_null;
767         struct EncryptedSecret es;
768
769         struct es_data *data = talloc_get_type(
770                 ldb_module_get_private(test_ctx->module),
771                 struct es_data);
772         int err = LDB_SUCCESS;
773         int rc;
774
775         plain_text = data_blob_string_const("A text value");
776         cipher_text = samba_encrypt_aead(
777                         &err,
778                         test_ctx,
779                         test_ctx->ldb,
780                         plain_text,
781                         data);
782         assert_int_equal(LDB_SUCCESS, err);
783
784         rc = ndr_pull_struct_blob(
785                 &cipher_text,
786                 test_ctx,
787                 &es,
788                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
789         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
790         assert_true(check_header(&es));
791
792         {
793                 struct PlaintextSecret *decrypted =
794                         talloc_zero(test_ctx, struct PlaintextSecret);
795                 samba_decrypt_aead(
796                         &err,
797                         test_ctx,
798                         test_ctx->ldb,
799                         &es,
800                         decrypted,
801                         data);
802                 assert_int_equal(LDB_SUCCESS, err);
803                 assert_int_equal(
804                         plain_text.length,
805                         decrypted->cleartext.length);
806                 assert_int_equal(0,
807                         data_blob_cmp(
808                                 &decrypted->cleartext,
809                                 &plain_text));
810         }
811         es.encrypted.data[0] = es.encrypted.data[0] ^ 0xff;
812         {
813                 struct PlaintextSecret *decrypted =
814                         talloc_zero(test_ctx, struct PlaintextSecret);
815                 samba_decrypt_aead(
816                         &err,
817                         test_ctx,
818                         test_ctx->ldb,
819                         &es,
820                         decrypted,
821                         data);
822                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
823         }
824 }
825
826 static void test_samba_altered_iv(void **state)
827 {
828         struct ldbtest_ctx *test_ctx =
829                 talloc_get_type_abort(*state, struct ldbtest_ctx);
830         struct ldb_val plain_text = data_blob_null;
831         struct ldb_val cipher_text = data_blob_null;
832         struct EncryptedSecret es;
833
834         struct es_data *data = talloc_get_type(
835                 ldb_module_get_private(test_ctx->module),
836                 struct es_data);
837         int err = LDB_SUCCESS;
838         int rc;
839
840         plain_text = data_blob_string_const("A text value");
841         cipher_text = samba_encrypt_aead(
842                         &err,
843                         test_ctx,
844                         test_ctx->ldb,
845                         plain_text,
846                         data);
847         assert_int_equal(LDB_SUCCESS, err);
848
849         rc = ndr_pull_struct_blob(
850                 &cipher_text,
851                 test_ctx,
852                 &es,
853                 (ndr_pull_flags_fn_t) ndr_pull_EncryptedSecret);
854         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
855         assert_true(check_header(&es));
856
857         {
858                 struct PlaintextSecret *decrypted =
859                         talloc_zero(test_ctx, struct PlaintextSecret);
860                 samba_decrypt_aead(
861                         &err,
862                         test_ctx,
863                         test_ctx->ldb,
864                         &es,
865                         decrypted,
866                         data);
867                 assert_int_equal(LDB_SUCCESS, err);
868                 assert_int_equal(
869                         plain_text.length,
870                         decrypted->cleartext.length);
871                 assert_int_equal(0,
872                         data_blob_cmp(
873                                 &decrypted->cleartext,
874                                 &plain_text));
875         }
876         es.iv.data[0] = es.iv.data[0] ^ 0xff;
877         {
878                 struct PlaintextSecret *decrypted =
879                         talloc_zero(test_ctx, struct PlaintextSecret);
880                 samba_decrypt_aead(
881                         &err,
882                         test_ctx,
883                         test_ctx->ldb,
884                         &es,
885                         decrypted,
886                         data);
887                 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, err);
888         }
889 }
890
891 /*
892  *  Test message encryption.
893  *  Test the secret attributes of a message are encrypted and decrypted.
894  *  Test that the non secret attributes are not encrypted.
895  *
896  */
897 static void test_message_encryption_decryption(void **state)
898 {
899         struct ldbtest_ctx *test_ctx =
900                 talloc_get_type_abort(*state, struct ldbtest_ctx);
901         struct ldb_context *ldb = test_ctx->ldb;
902         const char * const secrets[] = {DSDB_SECRET_ATTRIBUTES};
903         const size_t num_secrets
904                 = (sizeof(secrets)/sizeof(secrets[0]));
905         struct ldb_message *msg = ldb_msg_new(ldb);
906         const struct ldb_message *encrypted_msg = NULL;
907         struct es_data *data = talloc_get_type(
908                 ldb_module_get_private(test_ctx->module),
909                 struct es_data);
910         struct ldb_message_element *el = NULL;
911         int ret = LDB_SUCCESS;
912         int i, j;
913
914         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
915         ldb_msg_add_string(msg, "cmocka_test_name01", "value01");
916         for (i=0; i < num_secrets; i++) {
917                 ldb_msg_add_string(
918                         msg,
919                         secrets[i],
920                         secrets[i]);
921         }
922         ldb_msg_add_string(msg, "cmocka_test_name02", "value02");
923
924         encrypted_msg = encrypt_secret_attributes(
925                 &ret,
926                 test_ctx,
927                 test_ctx->ldb,
928                 msg,
929                 data);
930         assert_int_equal(LDB_SUCCESS, ret);
931
932         /*
933          * Check that all the secret attributes have been encrypted
934          *
935          */
936         for (i=0; i < num_secrets; i++) {
937                 el = ldb_msg_find_element(encrypted_msg, secrets[i]);
938                 assert_non_null(el);
939                 for (j = 0; j < el->num_values; j++) {
940                         int rc = LDB_SUCCESS;
941                         struct ldb_val dc = decrypt_value(
942                                 &rc,
943                                 test_ctx,
944                                 test_ctx->ldb,
945                                 el->values[j],
946                                 data);
947                         assert_int_equal(LDB_SUCCESS, rc);
948                         assert_memory_equal(
949                                 secrets[i],
950                                 dc.data,
951                                 dc.length);
952                         TALLOC_FREE(dc.data);
953                 }
954         }
955
956         /*
957          * Check that the normal attributes have not been encrypted
958          */
959         el = ldb_msg_find_element(encrypted_msg, "cmocka_test_name01");
960         assert_non_null(el);
961         assert_memory_equal(
962                 "value01",
963                 el->values[0].data,
964                 el->values[0].length);
965
966         el = ldb_msg_find_element(encrypted_msg, "cmocka_test_name02");
967         assert_non_null(el);
968         assert_memory_equal(
969                 "value02",
970                 el->values[0].data,
971                 el->values[0].length);
972
973         /*
974          * Now decrypt the message
975          */
976         ret = decrypt_secret_attributes(test_ctx->ldb,
977                                         discard_const(encrypted_msg),
978                                         data);
979         assert_int_equal(LDB_SUCCESS, ret);
980
981         /*
982          * Check that all the secret attributes have been decrypted
983          */
984         for (i=0; i < num_secrets; i++) {
985                 el = ldb_msg_find_element(encrypted_msg, secrets[i]);
986                 assert_non_null(el);
987                 for (j = 0; j < el->num_values; j++) {
988                         assert_memory_equal(
989                                 secrets[i],
990                                 el->values[j].data,
991                                 el->values[j].length);
992                 }
993         }
994
995         /*
996          * Check that the normal attributes are intact
997          */
998         el = ldb_msg_find_element(msg, "cmocka_test_name01");
999         assert_non_null(el);
1000         assert_memory_equal(
1001                 "value01",
1002                 el->values[0].data,
1003                 el->values[0].length);
1004
1005         el = ldb_msg_find_element(msg, "cmocka_test_name02");
1006         assert_non_null(el);
1007         assert_memory_equal(
1008                 "value02",
1009                 el->values[0].data,
1010                 el->values[0].length);
1011
1012 }
1013
1014 static void test_check_header(void **state)
1015 {
1016         struct ldbtest_ctx *test_ctx =
1017                 talloc_get_type_abort(*state, struct ldbtest_ctx);
1018
1019         struct ldb_val enc = data_blob_null;
1020         struct EncryptedSecret *es = NULL;
1021         int rc;
1022
1023         /*
1024          * Valid EncryptedSecret
1025          */
1026         es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
1027         rc = ndr_push_struct_blob(
1028                 &enc,
1029                 test_ctx,
1030                 es,
1031                 (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
1032         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
1033         assert_true(check_header(es));
1034         TALLOC_FREE(enc.data);
1035         TALLOC_FREE(es);
1036
1037         /*
1038          * invalid magic value
1039          */
1040         es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
1041         es->header.magic = 0xca5cadee;
1042         rc = ndr_push_struct_blob(
1043                 &enc,
1044                 test_ctx,
1045                 es,
1046                 (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
1047         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
1048         assert_false(check_header(es));
1049         TALLOC_FREE(enc.data);
1050         TALLOC_FREE(es);
1051
1052         /*
1053          * invalid version
1054          */
1055         es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
1056         es->header.version = SECRET_ATTRIBUTE_VERSION + 1;
1057         rc = ndr_push_struct_blob(
1058                 &enc,
1059                 test_ctx,
1060                 es,
1061                 (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
1062         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
1063         assert_false(check_header(es));
1064         TALLOC_FREE(enc.data);
1065         TALLOC_FREE(es);
1066
1067         /*
1068          * invalid algorithm
1069          */
1070         es = makeEncryptedSecret(test_ctx->ldb, test_ctx);
1071         es->header.algorithm = SECRET_ENCRYPTION_ALGORITHM + 1;
1072         rc = ndr_push_struct_blob(
1073                 &enc,
1074                 test_ctx,
1075                 es,
1076                 (ndr_push_flags_fn_t) ndr_push_EncryptedSecret);
1077         assert_true(NDR_ERR_CODE_IS_SUCCESS(rc));
1078         assert_false(check_header(es));
1079         TALLOC_FREE(enc.data);
1080         TALLOC_FREE(es);
1081 }
1082
1083 /*
1084  * Attempt to decrypt a message containing an unencrypted secret attribute
1085  * this should fail
1086  */
1087 static void test_unencrypted_secret(void **state)
1088 {
1089         struct ldbtest_ctx *test_ctx =
1090                 talloc_get_type_abort(*state, struct ldbtest_ctx);
1091         struct ldb_context *ldb = test_ctx->ldb;
1092         struct ldb_message *msg = ldb_msg_new(ldb);
1093         struct es_data *data = talloc_get_type(
1094                 ldb_module_get_private(test_ctx->module),
1095                 struct es_data);
1096         int ret = LDB_SUCCESS;
1097
1098         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
1099         ldb_msg_add_string(msg, "unicodePwd", "value01");
1100
1101         ret = decrypt_secret_attributes(test_ctx->ldb, msg, data);
1102         assert_int_equal(LDB_ERR_OPERATIONS_ERROR, ret);
1103 }
1104
1105
1106 int main(void) {
1107         const struct CMUnitTest tests[] = {
1108                 cmocka_unit_test_setup_teardown(
1109                         test_no_key_file,
1110                         setup,
1111                         teardown),
1112                 cmocka_unit_test_setup_teardown(
1113                         test_key_file,
1114                         setup,
1115                         teardown),
1116                 cmocka_unit_test_setup_teardown(
1117                         test_key_file_short_key,
1118                         setup,
1119                         teardown),
1120                 cmocka_unit_test_setup_teardown(
1121                         test_key_file_long_key,
1122                         setup,
1123                         teardown),
1124                 cmocka_unit_test_setup_teardown(
1125                         test_check_header,
1126                         setup,
1127                         teardown),
1128 #ifdef HAVE_GNUTLS_AEAD
1129                 cmocka_unit_test_setup_teardown(
1130                         test_gnutls_value_encryption,
1131                         setup_with_key,
1132                         teardown),
1133                 cmocka_unit_test_setup_teardown(
1134                         test_gnutls_altered_header,
1135                         setup_with_key,
1136                         teardown),
1137                 cmocka_unit_test_setup_teardown(
1138                         test_gnutls_altered_data,
1139                         setup_with_key,
1140                         teardown),
1141                 cmocka_unit_test_setup_teardown(
1142                         test_gnutls_altered_iv,
1143                         setup_with_key,
1144                         teardown),
1145 #endif /* HAVE_GNUTLS_AEAD */
1146                 cmocka_unit_test_setup_teardown(
1147                         test_samba_value_encryption,
1148                         setup_with_key,
1149                         teardown),
1150                 cmocka_unit_test_setup_teardown(
1151                         test_samba_altered_header,
1152                         setup_with_key,
1153                         teardown),
1154                 cmocka_unit_test_setup_teardown(
1155                         test_samba_altered_data,
1156                         setup_with_key,
1157                         teardown),
1158                 cmocka_unit_test_setup_teardown(
1159                         test_samba_altered_iv,
1160                         setup_with_key,
1161                         teardown),
1162                 cmocka_unit_test_setup_teardown(
1163                         test_message_encryption_decryption,
1164                         setup_with_key,
1165                         teardown),
1166                 cmocka_unit_test_setup_teardown(
1167                         test_unencrypted_secret,
1168                         setup_with_key,
1169                         teardown),
1170         };
1171
1172         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
1173         return cmocka_run_group_tests(tests, NULL, NULL);
1174 }