LCOV - code coverage report
Current view: top level - lib/crypto - test_gkdi.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 131 132 99.2 %
Date: 2024-05-31 13:13:24 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * Copyright (C) Catalyst.Net Ltd 2024
       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 <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <stdarg.h>
      21             : #include <stddef.h>
      22             : #include <stdint.h>
      23             : #include <setjmp.h>
      24             : #include <cmocka.h>
      25             : 
      26             : #include "replace.h"
      27             : #include <talloc.h>
      28             : #include "libcli/util/ntstatus.h"
      29             : #include "lib/crypto/gkdi.h"
      30             : #include "lib/crypto/gmsa.h"
      31             : 
      32             : #include "librpc/ndr/libndr.h"
      33             : #include "librpc/gen_ndr/gmsa.h"
      34             : #include "librpc/gen_ndr/ndr_gmsa.h"
      35             : #include "lib/util/time.h"
      36             : #include "libcli/security/dom_sid.h"
      37             : 
      38           1 : static void test_password_based_on_key_id(void **state)
      39             : {
      40           1 :         static const uint8_t root_key_data[] = {
      41             :                 152, 203, 215, 84,  113, 216, 118, 177, 81,  128, 50,  160, 148,
      42             :                 132, 82,  244, 65,  179, 164, 219, 209, 14,  33,  131, 178, 193,
      43             :                 80,  248, 126, 23,  66,  227, 45,  221, 171, 12,  247, 15,  62,
      44             :                 179, 164, 217, 123, 179, 106, 118, 228, 74,  12,  2,   241, 229,
      45             :                 139, 55,  237, 155, 220, 122, 200, 245, 129, 222, 37,  15};
      46           1 :         static const struct ProvRootKey root_key = {
      47             :                 .version = root_key_version_1,
      48             :                 .id = {.time_low = 0x170e972,
      49             :                        .time_mid = 0xa035,
      50             :                        .time_hi_and_version = 0xaf4c,
      51             :                        .clock_seq = {0x99, 0x3b},
      52             :                        .node = {0xe0, 0x52, 0xd5, 0xbd, 0x12, 0x16}},
      53             :                 .data =
      54             :                         {
      55             :                                 .data = discard_const_p(uint8_t, root_key_data),
      56             :                                 .length = sizeof root_key_data,
      57             :                         },
      58             :                 .create_time = 0,
      59             :                 .use_start_time = 0,
      60             :                 .domain_id = "example.com",
      61             :                 .kdf_algorithm = {
      62             :                         .id = KDF_ALGORITHM_SP800_108_CTR_HMAC,
      63             :                         .param.sp800_108 = KDF_PARAM_SHA512,
      64             :                 }};
      65           1 :         static const uint8_t expected[GMSA_PASSWORD_LEN] = {
      66             :                 114, 92,  31,  204, 138, 249, 1,   76,  192, 65,  52,  248, 247,
      67             :                 191, 30,  213, 25,  38,  81,  21,  183, 167, 154, 102, 190, 234,
      68             :                 234, 116, 114, 18,  141, 208, 143, 38,  178, 115, 195, 26,  199,
      69             :                 214, 176, 229, 128, 160, 147, 249, 245, 67,  165, 191, 192, 78,
      70             :                 224, 50,  115, 8,   207, 124, 178, 121, 67,  135, 125, 113, 79,
      71             :                 0,   131, 43,  74,  48,  171, 239, 183, 228, 50,  212, 202, 215,
      72             :                 188, 182, 94,  127, 117, 217, 91,  17,  90,  80,  158, 176, 204,
      73             :                 151, 244, 107, 139, 65,  94,  148, 216, 212, 97,  53,  54,  253,
      74             :                 6,   201, 94,  93,  250, 213, 12,  82,  162, 246, 197, 254, 205,
      75             :                 8,   19,  153, 66,  72,  60,  167, 28,  65,  39,  218, 147, 82,
      76             :                 162, 11,  177, 78,  231, 200, 66,  121, 9,   196, 240, 7,   148,
      77             :                 190, 151, 96,  214, 246, 7,   110, 85,  0,   246, 28,  121, 3,
      78             :                 61,  212, 204, 101, 153, 121, 100, 91,  65,  28,  225, 241, 123,
      79             :                 115, 105, 138, 74,  187, 74,  188, 59,  17,  201, 229, 158, 170,
      80             :                 184, 141, 237, 179, 246, 135, 104, 204, 56,  228, 156, 182, 26,
      81             :                 90,  151, 147, 25,  142, 47,  172, 183, 165, 222, 240, 95,  63,
      82             :                 79,  88,  35,  205, 76,  26,  229, 107, 46,  16,  202, 102, 196,
      83             :                 18,  140, 211, 242, 226, 198, 154, 97,  199, 44,  220, 186, 76,
      84             :                 215, 54,  196, 44,  140, 145, 252, 99,  229, 179, 74,  150, 154,
      85             :                 70,  226, 45,  122, 156, 156, 75,  83,  24};
      86           1 :         uint8_t out[GMSA_PASSWORD_NULL_TERMINATED_LEN];
      87           1 :         TALLOC_CTX *mem_ctx = NULL;
      88             : 
      89           1 :         mem_ctx = talloc_new(NULL);
      90           1 :         assert_non_null(mem_ctx);
      91             : 
      92             :         {
      93             :                 /* An arbitrary GKID. */
      94           1 :                 const struct Gkid gkid = {362, 0, 23};
      95             :                 /* An arbitrary time in the past. */
      96           1 :                 const NTTIME current_nt_time = 133524411756072082;
      97           1 :                 struct dom_sid account_sid;
      98           1 :                 NTSTATUS status;
      99           1 :                 bool ok;
     100             : 
     101           1 :                 ok = dom_sid_parse(
     102             :                         "S-1-5-21-4119591868-3001629103-3445594911-48026",
     103             :                         &account_sid);
     104           1 :                 assert_true(ok);
     105             : 
     106             :                 /* Derive a password from the root key. */
     107           1 :                 status = gmsa_password_based_on_key_id(mem_ctx,
     108             :                                                        gkid,
     109             :                                                        current_nt_time,
     110             :                                                        &root_key,
     111             :                                                        &account_sid,
     112             :                                                        out);
     113           1 :                 assert_true(NT_STATUS_IS_OK(status));
     114           1 :                 assert_memory_equal(expected, out, GMSA_PASSWORD_LEN);
     115             :         }
     116             : 
     117             :         {
     118           1 :                 uint64_t query_interval = 0;
     119           1 :                 uint64_t unchanged_interval = 0;
     120           1 :                 const struct MANAGEDPASSWORD_BLOB managed_pwd = {
     121             :                         .passwords = {
     122             :                                 .current = out,
     123             :                                 .query_interval = &query_interval,
     124             :                                 .unchanged_interval = &unchanged_interval}};
     125           1 :                 DATA_BLOB packed_blob = {};
     126           1 :                 enum ndr_err_code err;
     127             : 
     128           1 :                 err = ndr_push_struct_blob(
     129             :                         &packed_blob,
     130             :                         mem_ctx,
     131             :                         &managed_pwd,
     132             :                         (ndr_push_flags_fn_t)ndr_push_MANAGEDPASSWORD_BLOB);
     133           1 :                 assert_int_equal(NDR_ERR_SUCCESS, err);
     134             :         }
     135             : 
     136           1 :         talloc_free(mem_ctx);
     137           1 : }
     138             : 
     139          12 : static void assert_gkid_equal(const struct Gkid g1, const struct Gkid g2)
     140             : {
     141          12 :         assert_int_equal(g1.l0_idx, g2.l0_idx);
     142          12 :         assert_int_equal(g1.l1_idx, g2.l1_idx);
     143          12 :         assert_int_equal(g1.l2_idx, g2.l2_idx);
     144          12 : }
     145             : 
     146           1 : static void test_gkdi_rollover_interval(void **state)
     147             : {
     148           1 :         NTTIME interval;
     149           1 :         bool ok;
     150             : 
     151           1 :         ok = gkdi_rollover_interval(0, &interval);
     152           1 :         assert_true(ok);
     153           1 :         assert_int_equal(0, interval);
     154             : 
     155           1 :         ok = gkdi_rollover_interval(1, &interval);
     156           1 :         assert_true(ok);
     157           1 :         assert_int_equal(UINT64_C(720000000000), interval);
     158             : 
     159           1 :         ok = gkdi_rollover_interval(2, &interval);
     160           1 :         assert_true(ok);
     161           1 :         assert_int_equal(UINT64_C(1440000000000), interval);
     162             : 
     163           1 :         ok = gkdi_rollover_interval(3, &interval);
     164           1 :         assert_true(ok);
     165           1 :         assert_int_equal(UINT64_C(2520000000000), interval);
     166             : 
     167           1 :         ok = gkdi_rollover_interval(4, &interval);
     168           1 :         assert_true(ok);
     169           1 :         assert_int_equal(UINT64_C(3240000000000), interval);
     170             : 
     171           1 :         ok = gkdi_rollover_interval(5, &interval);
     172           1 :         assert_true(ok);
     173           1 :         assert_int_equal(UINT64_C(4320000000000), interval);
     174             : 
     175           1 :         ok = gkdi_rollover_interval(-1, &interval);
     176           1 :         assert_false(ok);
     177             : 
     178           1 :         ok = gkdi_rollover_interval(-2, &interval);
     179           1 :         assert_false(ok);
     180             : 
     181           1 :         ok = gkdi_rollover_interval(10675199, &interval);
     182           1 :         assert_true(ok);
     183           1 :         assert_int_equal(UINT64_C(9223371720000000000), interval);
     184             : 
     185           1 :         ok = gkdi_rollover_interval(-10675198, &interval);
     186           1 :         assert_false(ok);
     187             : 
     188           1 :         ok = gkdi_rollover_interval(10675200, &interval);
     189           1 :         assert_true(ok);
     190           1 :         assert_int_equal(UINT64_C(9223372800000000000), interval);
     191             : 
     192           1 :         ok = gkdi_rollover_interval(-10675199, &interval);
     193           1 :         assert_false(ok);
     194             : 
     195           1 :         ok = gkdi_rollover_interval(21350398, &interval);
     196             :         /*
     197             :          * If we accepted this high of an interval, the result would be
     198             :          * 18446743800000000000.
     199             :          */
     200           1 :         assert_false(ok);
     201             : 
     202           1 :         ok = gkdi_rollover_interval(-21350397, &interval);
     203           1 :         assert_false(ok);
     204             : 
     205           1 :         ok = gkdi_rollover_interval(21350399, &interval);
     206           1 :         assert_false(ok); /* too large to be represented */
     207             : 
     208           1 :         ok = gkdi_rollover_interval(-21350398, &interval);
     209           1 :         assert_false(ok); /* too small to be represented */
     210           1 : }
     211             : 
     212          12 : static void assert_get_interval_id(const NTTIME time,
     213             :                                    const struct Gkid expected_gkid)
     214             : {
     215             :         {
     216          12 :                 const bool valid = gkid_is_valid(expected_gkid);
     217          12 :                 assert_true(valid);
     218             :         }
     219             : 
     220             :         {
     221          12 :                 const struct Gkid interval_id = gkdi_get_interval_id(time);
     222          12 :                 assert_gkid_equal(expected_gkid, interval_id);
     223             :         }
     224          12 : }
     225             : 
     226           1 : static void test_get_interval_id(void **state)
     227             : {
     228           1 :         assert_get_interval_id(0, Gkid(0, 0, 0));
     229             : 
     230           1 :         assert_get_interval_id(gkdi_key_cycle_duration - 1, Gkid(0, 0, 0));
     231             : 
     232           1 :         assert_get_interval_id(gkdi_key_cycle_duration, Gkid(0, 0, 1));
     233             : 
     234           1 :         assert_get_interval_id(27 * gkdi_key_cycle_duration, Gkid(0, 0, 27));
     235             : 
     236           1 :         assert_get_interval_id((gkdi_l2_key_iteration - 1) *
     237             :                                        gkdi_key_cycle_duration,
     238             :                                Gkid(0, 0, gkdi_l2_key_iteration - 1));
     239             : 
     240           1 :         assert_get_interval_id(gkdi_l2_key_iteration * gkdi_key_cycle_duration,
     241             :                                Gkid(0, 1, 0));
     242             : 
     243           1 :         assert_get_interval_id(17 * gkdi_l2_key_iteration *
     244             :                                        gkdi_key_cycle_duration,
     245             :                                Gkid(0, 17, 0));
     246             : 
     247           1 :         assert_get_interval_id(((gkdi_l1_key_iteration - 1) *
     248             :                                         gkdi_l2_key_iteration +
     249             :                                 3) * gkdi_key_cycle_duration,
     250             :                                Gkid(0, gkdi_l1_key_iteration - 1, 3));
     251             : 
     252           1 :         assert_get_interval_id(gkdi_l1_key_iteration * gkdi_l2_key_iteration *
     253             :                                        gkdi_key_cycle_duration,
     254             :                                Gkid(1, 0, 0));
     255             : 
     256           1 :         assert_get_interval_id(((1234 * gkdi_l1_key_iteration + 8) *
     257             :                                         gkdi_l2_key_iteration +
     258             :                                 13) * gkdi_key_cycle_duration,
     259             :                                Gkid(1234, 8, 13));
     260             : 
     261           1 :         assert_get_interval_id(INT64_MAX, Gkid(25019, 31, 29));
     262             : 
     263           1 :         assert_get_interval_id(UINT64_MAX, Gkid(50039, 31, 27));
     264           1 : }
     265             : 
     266           1 : static void test_get_key_start_time(void **state)
     267             : {
     268           1 :         NTTIME start_time = 0;
     269           1 :         bool ok;
     270             : 
     271             :         /* Try passing an invalid GKID. */
     272           1 :         ok = gkdi_get_key_start_time(invalid_gkid, &start_time);
     273           1 :         assert_false(ok);
     274             : 
     275             :         /* Try passing an L1 GKID rather than an L2 GKID. */
     276           1 :         ok = gkdi_get_key_start_time(Gkid(0, 0, -1), &start_time);
     277           1 :         assert_false(ok);
     278             : 
     279             :         /* Test some L2 GKIDs. */
     280             : 
     281           1 :         ok = gkdi_get_key_start_time(Gkid(0, 0, 0), &start_time);
     282           1 :         assert_true(ok);
     283           1 :         assert_int_equal(0, start_time);
     284             : 
     285           1 :         ok = gkdi_get_key_start_time(Gkid(0, 0, 1), &start_time);
     286           1 :         assert_true(ok);
     287           1 :         assert_int_equal(gkdi_key_cycle_duration, start_time);
     288             : 
     289           1 :         ok = gkdi_get_key_start_time(Gkid(123, 18, 2), &start_time);
     290           1 :         assert_true(ok);
     291           1 :         assert_int_equal(126530 * gkdi_key_cycle_duration, start_time);
     292             : 
     293           1 :         ok = gkdi_get_key_start_time(Gkid(25019, 31, 29), &start_time);
     294           1 :         assert_true(ok);
     295           1 :         assert_int_equal(25620477 * gkdi_key_cycle_duration, start_time);
     296             : 
     297           1 :         ok = gkdi_get_key_start_time(Gkid(25019, 31, 30), &start_time);
     298           1 :         assert_true(ok);
     299           1 :         assert_int_equal(UINT64_C(25620478) * gkdi_key_cycle_duration,
     300             :                          start_time);
     301             : 
     302           1 :         ok = gkdi_get_key_start_time(Gkid(50039, 31, 27), &start_time);
     303           1 :         assert_true(ok);
     304           1 :         assert_int_equal(UINT64_C(51240955) * gkdi_key_cycle_duration,
     305             :                          start_time);
     306             : 
     307             :         /*
     308             :          * Test GKIDs so high that their start times can’t be represented in
     309             :          * NTTIME.
     310             :          */
     311             : 
     312           1 :         ok = gkdi_get_key_start_time(Gkid(50039, 31, 28), &start_time);
     313           1 :         assert_false(ok);
     314             : 
     315           1 :         ok = gkdi_get_key_start_time(Gkid(INT32_MAX, 31, 31), &start_time);
     316           1 :         assert_false(ok);
     317           1 : }
     318             : 
     319           1 : int main(int argc, char *argv[])
     320             : {
     321           1 :         const struct CMUnitTest tests[] = {
     322             :                 cmocka_unit_test(test_password_based_on_key_id),
     323             :                 cmocka_unit_test(test_gkdi_rollover_interval),
     324             :                 cmocka_unit_test(test_get_interval_id),
     325             :                 cmocka_unit_test(test_get_key_start_time),
     326             :         };
     327             : 
     328           1 :         if (argc == 2) {
     329           0 :                 cmocka_set_test_filter(argv[1]);
     330             :         }
     331           1 :         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     332           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
     333             : }

Generated by: LCOV version 1.14