2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Catalyst.Net Ltd 2023
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.
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.
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/>.
28 #include "libcli/util/ntstatus.h"
29 #include "lib/crypto/gkdi.h"
31 static const uint8_t gmsa_security_descriptor
[] = {
32 /* O:SYD:(A;;FRFW;;;S-1-5-9) */
33 0x01, 0x00, 0x04, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x00,
35 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00,
36 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00,
37 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00};
39 #define GKID(l0_idx_, l1_idx_, l2_idx_) \
40 ((struct Gkid){.l0_idx = l0_idx_, .l1_idx = l1_idx_, .l2_idx = l2_idx_})
42 #define GUID_LITERAL( \
43 time_low_, time_mid_, time_hi_and_version_, clock_seq_, node_) \
44 ((struct GUID){.time_low = (0x##time_low_), \
45 .time_mid = (0x##time_mid_), \
46 .time_hi_and_version = (0x##time_hi_and_version_), \
47 .clock_seq = {(uint32_t)(0x##clock_seq_) >> 8, \
48 (uint8_t)(0x##clock_seq_)}, \
49 .node = {(uint64_t)(0x##node_) >> 40, \
50 (uint8_t)((uint64_t)(0x##node_) >> 32), \
51 (uint8_t)((uint64_t)(0x##node_) >> 24), \
52 (uint8_t)((uint64_t)(0x##node_) >> 16), \
53 (uint8_t)((uint64_t)(0x##node_) >> 8), \
54 (uint8_t)(0x##node_)}})
57 const char *name
; /* The name of the test scenario. */
58 struct Gkid gkid
; /* The GKID of the key to derive. */
59 struct ProvRootKey root_key
;
60 NTSTATUS expected_status
;
61 uint8_t expected_key
[GKDI_KEY_LEN
]; /* The expected derived key. */
64 #define DATA_BLOB_CONST(data_, length_) \
65 ((DATA_BLOB){.data = (discard_const_p(uint8_t, data_)), \
68 #define ARRAY(...) ((const uint8_t[]){__VA_ARGS__})
69 #define ROOT_KEY_DATA(...) \
70 DATA_BLOB_CONST(ARRAY(__VA_ARGS__), sizeof(ARRAY(__VA_ARGS__)))
71 #define EXPECTED_KEY(...) {__VA_ARGS__}
72 #define ROOT_KEY_VERSION(version) (version)
74 #define ARBITRARY_ROOT_KEY_DATA \
75 ROOT_KEY_DATA(72, 159, 53, 49, 197, 55, 119, 77, 67, 45, 107, \
76 151, 227, 188, 31, 67, 210, 232, 198, 220, 23, 235, \
77 14, 79, 217, 160, 135, 13, 47, 30, 191, 146, 226, \
78 73, 102, 104, 168, 181, 189, 17, 174, 162, 211, 45, \
79 10, 171, 113, 111, 72, 254, 86, 159, 92, 155, 80, \
80 255, 63, 155, 245, 222, 174, 165, 114, 251)
82 #define ARBITRARY_GUID GUID_LITERAL(4cdf4285, c46a, 62a3, 2f7d, 95f97342685b)
84 #define SUCCESS_VECTOR( \
85 name_, root_key_id, algorithm, gkid_, root_key_data, expected_key_) \
87 .name = (name_), .gkid = (gkid_), \
88 .root_key = {.version = root_key_version_1, \
89 .id = (root_key_id), \
90 .data = (root_key_data), \
92 {.id = KDF_ALGORITHM_SP800_108_CTR_HMAC, \
93 .param.sp800_108 = (algorithm)}}, \
94 .expected_status = NT_STATUS_OK, \
95 .expected_key = expected_key_, \
98 #define FAILURE_VECTOR_VERSION(name_, \
106 .name = (name_), .gkid = (gkid_), \
107 .root_key = {.version = (root_key_version), \
108 .id = (root_key_id), \
109 .data = (root_key_data), \
111 {.id = KDF_ALGORITHM_SP800_108_CTR_HMAC, \
112 .param.sp800_108 = (algorithm)}}, \
113 .expected_status = (expected_status_), .expected_key = {}, \
116 #define FAILURE_VECTOR( \
117 name_, root_key_id, algorithm, gkid_, root_key_data, expected_status_) \
118 FAILURE_VECTOR_VERSION(name_, \
122 root_key_version_1, \
126 /* Test vectors derived from samba.tests.krb5.gkdi_tests Python tests. */
127 static const struct test_vector gkdi_vectors
[] = {
129 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_current_l0_idx_"
131 GUID_LITERAL(89f70521
, 9d66
, 441f
, c314
, 1b462f9b1052
),
134 ROOT_KEY_DATA(166, 239, 135, 219, 187, 248, 107, 107, 190, 85,
135 117, 11, 148, 31, 19, 202, 153, 239, 229, 24,
136 94, 46, 43, 222, 213, 184, 56, 216, 160, 231,
137 118, 71, 5, 55, 230, 140, 174, 69, 167, 160,
138 244, 177, 214, 201, 191, 84, 148, 195, 248, 121,
139 225, 114, 227, 38, 85, 124, 219, 182, 165, 110,
141 EXPECTED_KEY(189, 83, 138, 7, 52, 144, 243, 207, 148, 81,
142 201, 51, 2, 93, 233, 178, 44, 151, 234, 221,
143 175, 250, 148, 179, 121, 226, 185, 25, 164, 190,
144 209, 71, 91, 198, 127, 106, 145, 117, 177, 57,
145 198, 146, 4, 197, 125, 67, 0, 160, 20, 31,
146 254, 52, 209, 44, 237, 132, 97, 69, 147, 177,
149 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_current_l0_idx_"
151 GUID_LITERAL(1a3d6c30
, aa81
, cb7f
, d3fe
, 80775d135dfe
),
154 ROOT_KEY_DATA(223, 217, 91, 227, 21, 58, 8, 5, 198, 86,
155 148, 231, 210, 132, 170, 206, 90, 176, 170, 73,
156 51, 80, 2, 94, 184, 219, 198, 223, 11, 78,
157 146, 86, 251, 76, 191, 190, 98, 55, 206, 55,
158 50, 105, 78, 38, 8, 118, 0, 118, 182, 112,
159 130, 211, 154, 189, 60, 15, 237, 186, 27, 136,
161 EXPECTED_KEY(187, 189, 147, 118, 205, 22, 194, 71, 237, 64,
162 245, 145, 45, 25, 8, 33, 140, 8, 240, 145,
163 91, 174, 2, 254, 2, 203, 251, 55, 83, 189,
164 228, 6, 249, 197, 83, 172, 217, 81, 67, 207,
165 99, 144, 106, 4, 64, 227, 207, 35, 125, 35,
166 53, 174, 78, 75, 156, 210, 217, 70, 167, 19,
169 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_current_l0_idx_"
170 "both_seed_keys (next older L1)",
171 GUID_LITERAL(09de0b38
, c743
, 7abf
, 44ea
, 7a3c3e404314
),
174 ROOT_KEY_DATA(213, 145, 45, 14, 179, 189, 96, 225, 55, 27,
175 30, 82, 93, 216, 59, 231, 252, 91, 175, 119,
176 1, 139, 13, 186, 107, 217, 72, 183, 169, 142,
177 190, 90, 243, 118, 116, 51, 37, 6, 164, 108,
178 82, 193, 8, 166, 47, 42, 62, 137, 37, 26,
179 209, 189, 230, 213, 57, 0, 70, 121, 192, 101,
181 EXPECTED_KEY(177, 247, 197, 137, 110, 125, 199, 145, 217, 192,
182 170, 248, 202, 125, 186, 184, 193, 114, 164, 248,
183 184, 115, 219, 72, 138, 60, 76, 189, 15, 85,
184 155, 17, 82, 255, 186, 57, 212, 175, 242, 217,
185 232, 170, 218, 144, 178, 122, 60, 148, 165, 175,
186 153, 111, 75, 143, 88, 74, 79, 55, 204, 171,
189 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_current_l0_idx_"
190 "both_seed_keys (L2)",
191 GUID_LITERAL(09de0b38
, c743
, 7abf
, 44ea
, 7a3c3e404314
),
194 ROOT_KEY_DATA(213, 145, 45, 14, 179, 189, 96, 225, 55, 27,
195 30, 82, 93, 216, 59, 231, 252, 91, 175, 119,
196 1, 139, 13, 186, 107, 217, 72, 183, 169, 142,
197 190, 90, 243, 118, 116, 51, 37, 6, 164, 108,
198 82, 193, 8, 166, 47, 42, 62, 137, 37, 26,
199 209, 189, 230, 213, 57, 0, 70, 121, 192, 101,
201 EXPECTED_KEY(19, 60, 155, 189, 32, 217, 34, 122, 235, 56,
202 223, 205, 59, 230, 188, 191, 197, 152, 59, 163,
203 114, 2, 8, 143, 245, 200, 167, 5, 17, 33,
204 69, 6, 166, 156, 25, 90, 136, 7, 205, 132,
205 75, 203, 149, 94, 149, 105, 200, 228, 209, 151,
206 117, 159, 40, 87, 124, 193, 38, 209, 95, 22,
209 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_previous_l0_"
211 GUID_LITERAL(27136e8f
, e093
, 6fe3
, e57f
, 1d915b102e1c
),
214 ROOT_KEY_DATA(180, 17, 24, 198, 10, 25, 202, 250, 94, 207,
215 133, 141, 26, 42, 34, 22, 82, 123, 45, 174,
216 223, 56, 110, 157, 89, 158, 66, 164, 106, 221,
217 108, 125, 201, 56, 104, 97, 151, 97, 200, 128,
218 255, 54, 116, 167, 124, 110, 95, 191, 52, 52,
219 209, 48, 169, 114, 123, 178, 205, 42, 37, 87,
221 EXPECTED_KEY(147, 92, 189, 192, 97, 152, 235, 40, 250, 68,
222 184, 216, 39, 143, 81, 7, 44, 70, 19, 153,
223 146, 54, 88, 80, 65, 237, 232, 231, 45, 2,
224 254, 149, 227, 69, 79, 4, 99, 130, 203, 192,
225 167, 0, 119, 155, 121, 71, 77, 215, 224, 128,
226 80, 157, 118, 48, 45, 41, 55, 64, 126, 150,
229 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha1 (next "
231 GUID_LITERAL(970abad6
, fe55
, 073a
, caf1
, b801d3f26bd3
),
234 ROOT_KEY_DATA(59, 237, 3, 191, 15, 183, 212, 1, 49, 73,
235 21, 79, 36, 202, 45, 89, 185, 141, 182, 213,
236 136, 203, 31, 84, 236, 160, 131, 133, 94, 37,
237 235, 40, 211, 86, 42, 1, 173, 199, 140, 75,
238 112, 224, 183, 42, 89, 81, 88, 99, 231, 115,
239 43, 133, 63, 186, 2, 221, 118, 70, 230, 49,
241 EXPECTED_KEY(87, 108, 182, 143, 46, 82, 235, 115, 159, 129,
242 123, 72, 140, 53, 144, 216, 111, 28, 44, 54,
243 95, 63, 201, 32, 29, 156, 127, 238, 116, 148,
244 133, 61, 88, 116, 110, 225, 62, 72, 241, 138,
245 166, 250, 105, 247, 21, 125, 227, 208, 125, 227,
246 78, 19, 131, 103, 146, 183, 192, 136, 255, 182,
249 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha1 (L2)",
250 GUID_LITERAL(970abad6
, fe55
, 073a
, caf1
, b801d3f26bd3
),
253 ROOT_KEY_DATA(59, 237, 3, 191, 15, 183, 212, 1, 49, 73,
254 21, 79, 36, 202, 45, 89, 185, 141, 182, 213,
255 136, 203, 31, 84, 236, 160, 131, 133, 94, 37,
256 235, 40, 211, 86, 42, 1, 173, 199, 140, 75,
257 112, 224, 183, 42, 89, 81, 88, 99, 231, 115,
258 43, 133, 63, 186, 2, 221, 118, 70, 230, 49,
260 EXPECTED_KEY(63, 251, 130, 90, 218, 241, 22, 182, 83, 50,
261 7, 213, 104, 163, 14, 211, 211, 242, 28, 104,
262 132, 9, 65, 201, 69, 102, 132, 249, 175, 161,
263 27, 5, 110, 12, 89, 57, 27, 77, 136, 196,
264 149, 217, 132, 195, 214, 128, 2, 156, 197, 197,
265 148, 99, 15, 52, 23, 145, 25, 193, 197, 172,
268 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha256 (next "
270 GUID_LITERAL(45e26207
, ed33
, dcd5
, 925a
, 518a0deef69e
),
273 ROOT_KEY_DATA(40, 181, 182, 80, 61, 60, 29, 36, 129, 77,
274 231, 129, 187, 123, 252, 227, 239, 105, 238, 209,
275 206, 72, 9, 55, 43, 238, 44, 80, 98, 112,
276 197, 240, 181, 198, 223, 89, 116, 114, 98, 63,
277 37, 108, 134, 218, 160, 153, 30, 138, 17, 161,
278 112, 95, 33, 178, 207, 220, 11, 185, 219, 75,
280 EXPECTED_KEY(87, 172, 237, 110, 117, 248, 63, 58, 244, 248,
281 121, 179, 139, 96, 240, 144, 180, 46, 75, 250,
282 2, 47, 174, 62, 111, 217, 66, 128, 180, 105,
283 176, 236, 21, 216, 184, 83, 168, 112, 181, 251,
284 223, 40, 112, 140, 206, 25, 39, 59, 116, 165,
285 115, 172, 190, 13, 237, 168, 239, 81, 93, 180,
288 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha256 (L2)",
289 GUID_LITERAL(45e26207
, ed33
, dcd5
, 925a
, 518a0deef69e
),
292 ROOT_KEY_DATA(40, 181, 182, 80, 61, 60, 29, 36, 129, 77,
293 231, 129, 187, 123, 252, 227, 239, 105, 238, 209,
294 206, 72, 9, 55, 43, 238, 44, 80, 98, 112,
295 197, 240, 181, 198, 223, 89, 116, 114, 98, 63,
296 37, 108, 134, 218, 160, 153, 30, 138, 17, 161,
297 112, 95, 33, 178, 207, 220, 11, 185, 219, 75,
299 EXPECTED_KEY(117, 42, 8, 121, 174, 36, 36, 192, 80, 76,
300 116, 147, 89, 159, 19, 229, 136, 225, 187, 220,
301 37, 47, 131, 50, 90, 213, 177, 251, 145, 194,
302 76, 137, 1, 212, 64, 243, 255, 159, 251, 165,
303 159, 205, 101, 187, 151, 87, 50, 217, 243, 131,
304 221, 80, 184, 152, 23, 75, 185, 57, 62, 56,
307 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha384 (next "
309 GUID_LITERAL(66e6d9f7
, 4924, f3fc
, fe34
, 605634d42ebd
),
312 ROOT_KEY_DATA(35, 229, 186, 134, 203, 216, 143, 123, 67, 46,
313 230, 109, 187, 3, 191, 78, 235, 244, 1, 203,
314 252, 61, 247, 53, 212, 215, 40, 181, 3, 200,
315 127, 132, 50, 7, 198, 246, 21, 63, 25, 13,
316 254, 133, 168, 108, 184, 216, 183, 77, 241, 59,
317 37, 48, 89, 129, 190, 141, 126, 41, 201, 110,
319 EXPECTED_KEY(250, 186, 221, 122, 154, 99, 223, 87, 214, 131,
320 45, 247, 167, 53, 174, 187, 110, 24, 24, 136,
321 178, 234, 243, 1, 162, 228, 255, 154, 112, 36,
322 109, 56, 171, 29, 36, 22, 50, 91, 243, 235,
323 114, 106, 2, 103, 186, 180, 189, 149, 12, 114,
324 145, 240, 94, 165, 241, 113, 151, 236, 229, 105,
327 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_sha384 (L2)",
328 GUID_LITERAL(66e6d9f7
, 4924, f3fc
, fe34
, 605634d42ebd
),
331 ROOT_KEY_DATA(35, 229, 186, 134, 203, 216, 143, 123, 67, 46,
332 230, 109, 187, 3, 191, 78, 235, 244, 1, 203,
333 252, 61, 247, 53, 212, 215, 40, 181, 3, 200,
334 127, 132, 50, 7, 198, 246, 21, 63, 25, 13,
335 254, 133, 168, 108, 184, 216, 183, 77, 241, 59,
336 37, 48, 89, 129, 190, 141, 126, 41, 201, 110,
338 EXPECTED_KEY(236, 28, 101, 99, 75, 86, 148, 129, 142, 29,
339 52, 29, 169, 153, 109, 184, 242, 161, 239, 106,
340 44, 119, 106, 113, 38, 167, 235, 209, 139, 55,
341 160, 115, 175, 218, 196, 76, 65, 177, 103, 177,
342 78, 75, 135, 45, 72, 91, 187, 109, 123, 112,
343 150, 66, 21, 208, 232, 74, 47, 241, 66, 169,
346 "samba.tests.krb5.gkdi_tests.GkdiSelfTests.test_derive_key_"
348 GUID_LITERAL(d95fb06f
, 5a9c
, 1829, e20d
, 27f3f2ecfbeb
),
351 ROOT_KEY_DATA(72, 159, 53, 49, 197, 55, 119, 77, 67, 45,
352 107, 151, 227, 188, 31, 67, 210, 232, 198, 220,
353 23, 235, 14, 79, 217, 160, 135, 13, 47, 30,
354 191, 146, 226, 73, 102, 104, 168, 181, 189, 17,
355 174, 162, 211, 45, 10, 171, 113, 111, 72, 254,
356 86, 159, 92, 155, 80, 255, 63, 155, 245, 222,
358 EXPECTED_KEY(214, 171, 59, 20, 244, 244, 200, 144, 138, 163,
359 70, 64, 17, 179, 159, 16, 168, 191, 173, 185,
360 151, 74, 249, 15, 125, 154, 159, 237, 226, 253,
361 198, 229, 246, 138, 98, 142, 192, 15, 153, 148,
362 163, 171, 216, 165, 42, 233, 226, 219, 79, 104,
363 232, 54, 72, 49, 30, 157, 119, 101, 242, 83,
365 FAILURE_VECTOR_VERSION("unsupported root key version (0)",
370 ARBITRARY_ROOT_KEY_DATA
,
371 NT_STATUS_NOT_SUPPORTED
),
372 FAILURE_VECTOR_VERSION("unsupported root key version (2)",
377 ARBITRARY_ROOT_KEY_DATA
,
378 NT_STATUS_NOT_SUPPORTED
),
379 FAILURE_VECTOR("unsupported algorithm (−1)",
381 -1 /* an unsupported algorithm */,
383 ARBITRARY_ROOT_KEY_DATA
,
384 NT_STATUS_NOT_SUPPORTED
),
385 FAILURE_VECTOR("wrong length (32 bytes short) for root key data",
389 ROOT_KEY_DATA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
390 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
391 22, 23, 24, 25, 26, 27, 28, 29, 30, 31),
392 NT_STATUS_NOT_SUPPORTED
),
393 FAILURE_VECTOR("default GKID (−1, −1, −1)",
397 ARBITRARY_ROOT_KEY_DATA
,
398 NT_STATUS_INVALID_PARAMETER
),
399 FAILURE_VECTOR("invalid GKID (−2, −1, −1)",
403 ARBITRARY_ROOT_KEY_DATA
,
404 NT_STATUS_INVALID_PARAMETER
),
405 FAILURE_VECTOR("invalid GKID (−1, 0, 0)",
409 ARBITRARY_ROOT_KEY_DATA
,
410 NT_STATUS_INVALID_PARAMETER
),
411 FAILURE_VECTOR("invalid GKID (0, −1, 0)",
415 ARBITRARY_ROOT_KEY_DATA
,
416 NT_STATUS_INVALID_PARAMETER
),
417 FAILURE_VECTOR("invalid GKID (0, −2, −1)",
421 ARBITRARY_ROOT_KEY_DATA
,
422 NT_STATUS_INVALID_PARAMETER
),
423 FAILURE_VECTOR("invalid GKID (0, 0, −2)",
427 ARBITRARY_ROOT_KEY_DATA
,
428 NT_STATUS_INVALID_PARAMETER
),
429 FAILURE_VECTOR("invalid GKID (123, 0, 32)",
433 ARBITRARY_ROOT_KEY_DATA
,
434 NT_STATUS_INVALID_PARAMETER
),
435 FAILURE_VECTOR("invalid GKID (456, 32, 0)",
439 ARBITRARY_ROOT_KEY_DATA
,
440 NT_STATUS_INVALID_PARAMETER
),
441 FAILURE_VECTOR("try to derive L0 seed key (333, −1, −1)",
445 ARBITRARY_ROOT_KEY_DATA
,
446 NT_STATUS_INVALID_PARAMETER
),
449 static void test_gkdi_key_derivation(void **state
)
451 TALLOC_CTX
*mem_ctx
= NULL
;
454 mem_ctx
= talloc_new(NULL
);
455 assert_non_null(mem_ctx
);
457 for (n
= 0; n
< ARRAY_SIZE(gkdi_vectors
); ++n
) {
458 const struct test_vector
*test_vector
= &gkdi_vectors
[n
];
459 uint8_t out
[GKDI_KEY_LEN
] = {};
462 print_message("Running: %s\n", test_vector
->name
);
464 status
= compute_seed_key(
466 DATA_BLOB_CONST(gmsa_security_descriptor
,
467 sizeof gmsa_security_descriptor
),
468 &test_vector
->root_key
,
471 assert_int_equal(NT_STATUS_V(test_vector
->expected_status
),
472 NT_STATUS_V(status
));
473 assert_memory_equal(test_vector
->expected_key
,
478 talloc_free(mem_ctx
);
481 int main(int argc
, char *argv
[])
483 static const struct CMUnitTest tests
[] = {
484 cmocka_unit_test(test_gkdi_key_derivation
),
488 cmocka_set_test_filter(argv
[1]);
490 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
491 return cmocka_run_group_tests(tests
, NULL
, NULL
);