2 Unix SMB/CIFS implementation.
3 Group Key Distribution Protocol functions
5 Copyright (C) Catalyst.Net Ltd 2024
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
23 #include <ldb_errors.h>
24 #include <ldb_module.h>
25 #include "lib/crypto/gkdi.h"
26 #include "lib/util/data_blob.h"
27 #include "lib/util/samba_util.h"
28 #include "lib/util/util_str_hex.h"
29 #include "librpc/ndr/libndr.h"
30 #include "dsdb/gmsa/gkdi.h"
31 #include "dsdb/samdb/ldb_modules/util.h"
32 #include "dsdb/samdb/samdb.h"
34 static int gkdi_create_root_key(TALLOC_CTX *mem_ctx,
35 struct ldb_context *const ldb,
36 const NTTIME current_time,
37 const NTTIME use_start_time,
38 struct GUID *const root_key_id_out,
39 struct ldb_dn **const root_key_dn_out)
41 TALLOC_CTX *tmp_ctx = NULL;
42 struct GUID root_key_id;
43 struct ldb_message *add_msg = NULL;
44 NTSTATUS status = NT_STATUS_OK;
45 int ret = LDB_SUCCESS;
47 *root_key_dn_out = NULL;
49 tmp_ctx = talloc_new(mem_ctx);
50 if (tmp_ctx == NULL) {
55 add_msg = ldb_msg_new(tmp_ctx);
56 if (add_msg == NULL) {
61 ret = ldb_msg_append_string(add_msg,
70 uint8_t root_key_data[GKDI_KEY_LEN];
71 const DATA_BLOB root_key_data_blob = {
72 .data = root_key_data, .length = sizeof root_key_data};
74 generate_secret_buffer(root_key_data, sizeof root_key_data);
76 ret = ldb_msg_append_value(add_msg,
85 ret = samdb_msg_append_uint64(ldb,
95 ret = samdb_msg_append_uint64(ldb,
106 struct ldb_dn *domain_dn = NULL;
108 ret = samdb_server_reference_dn(ldb, tmp_ctx, &domain_dn);
113 ret = ldb_msg_append_linearized_dn(add_msg,
122 ret = ldb_msg_append_string(add_msg,
130 ret = ldb_msg_append_string(add_msg,
131 "msKds-KDFAlgorithmID",
132 "SP800_108_CTR_HMAC",
138 ret = ldb_msg_append_string(add_msg,
139 "msKds-SecretAgreementAlgorithmID",
147 static const uint8_t ffc_dh_parameters[] = {
148 12, 2, 0, 0, 68, 72, 80, 77, 0, 1, 0,
149 0, 135, 168, 230, 29, 180, 182, 102, 60, 255, 187,
150 209, 156, 101, 25, 89, 153, 140, 238, 246, 8, 102,
151 13, 208, 242, 93, 44, 238, 212, 67, 94, 59, 0,
152 224, 13, 248, 241, 214, 25, 87, 212, 250, 247, 223,
153 69, 97, 178, 170, 48, 22, 195, 217, 17, 52, 9,
154 111, 170, 59, 244, 41, 109, 131, 14, 154, 124, 32,
155 158, 12, 100, 151, 81, 122, 189, 90, 138, 157, 48,
156 107, 207, 103, 237, 145, 249, 230, 114, 91, 71, 88,
157 192, 34, 224, 177, 239, 66, 117, 191, 123, 108, 91,
158 252, 17, 212, 95, 144, 136, 185, 65, 245, 78, 177,
159 229, 155, 184, 188, 57, 160, 191, 18, 48, 127, 92,
160 79, 219, 112, 197, 129, 178, 63, 118, 182, 58, 202,
161 225, 202, 166, 183, 144, 45, 82, 82, 103, 53, 72,
162 138, 14, 241, 60, 109, 154, 81, 191, 164, 171, 58,
163 216, 52, 119, 150, 82, 77, 142, 246, 161, 103, 181,
164 164, 24, 37, 217, 103, 225, 68, 229, 20, 5, 100,
165 37, 28, 202, 203, 131, 230, 180, 134, 246, 179, 202,
166 63, 121, 113, 80, 96, 38, 192, 184, 87, 246, 137,
167 150, 40, 86, 222, 212, 1, 10, 189, 11, 230, 33,
168 195, 163, 150, 10, 84, 231, 16, 195, 117, 242, 99,
169 117, 215, 1, 65, 3, 164, 181, 67, 48, 193, 152,
170 175, 18, 97, 22, 210, 39, 110, 17, 113, 95, 105,
171 56, 119, 250, 215, 239, 9, 202, 219, 9, 74, 233,
172 30, 26, 21, 151, 63, 179, 44, 155, 115, 19, 77,
173 11, 46, 119, 80, 102, 96, 237, 189, 72, 76, 167,
174 177, 143, 33, 239, 32, 84, 7, 244, 121, 58, 26,
175 11, 161, 37, 16, 219, 193, 80, 119, 190, 70, 63,
176 255, 79, 237, 74, 172, 11, 181, 85, 190, 58, 108,
177 27, 12, 107, 71, 177, 188, 55, 115, 191, 126, 140,
178 111, 98, 144, 18, 40, 248, 194, 140, 187, 24, 165,
179 90, 227, 19, 65, 0, 10, 101, 1, 150, 249, 49,
180 199, 122, 87, 242, 221, 244, 99, 229, 233, 236, 20,
181 75, 119, 125, 230, 42, 170, 184, 168, 98, 138, 195,
182 118, 210, 130, 214, 237, 56, 100, 230, 121, 130, 66,
183 142, 188, 131, 29, 20, 52, 143, 111, 47, 145, 147,
184 181, 4, 90, 242, 118, 113, 100, 225, 223, 201, 103,
185 193, 251, 63, 46, 85, 164, 189, 27, 255, 232, 59,
186 156, 128, 208, 82, 185, 133, 209, 130, 234, 10, 219,
187 42, 59, 115, 19, 211, 254, 20, 200, 72, 75, 30,
188 5, 37, 136, 185, 183, 210, 187, 210, 223, 1, 97,
189 153, 236, 208, 110, 21, 87, 205, 9, 21, 179, 53,
190 59, 187, 100, 224, 236, 55, 127, 208, 40, 55, 13,
191 249, 43, 82, 199, 137, 20, 40, 205, 198, 126, 182,
192 24, 75, 82, 61, 29, 178, 70, 195, 47, 99, 7,
193 132, 144, 240, 14, 248, 214, 71, 209, 72, 212, 121,
194 84, 81, 94, 35, 39, 207, 239, 152, 197, 130, 102,
195 75, 76, 15, 108, 196, 22, 89};
196 const DATA_BLOB ffc_dh_parameters_blob = {
197 discard_const_p(uint8_t, ffc_dh_parameters),
198 sizeof ffc_dh_parameters};
200 ret = ldb_msg_append_value(add_msg,
201 "msKds-SecretAgreementParam",
202 &ffc_dh_parameters_blob,
209 ret = ldb_msg_append_string(add_msg,
210 "msKds-PublicKeyLength",
217 ret = ldb_msg_append_string(add_msg,
218 "msKds-PrivateKeyLength",
226 static const uint8_t kdf_parameters[] = {
227 0, 0, 0, 0, 1, 0, 0, 0, 14, 0,
228 0, 0, 0, 0, 0, 0, 'S', 0, 'H', 0,
229 'A', 0, '5', 0, '1', 0, '2', 0, 0, 0,
231 const DATA_BLOB kdf_parameters_blob = {
232 discard_const_p(uint8_t, kdf_parameters),
233 sizeof kdf_parameters};
235 ret = ldb_msg_append_value(add_msg,
237 &kdf_parameters_blob,
245 uint8_t guid_buf[sizeof((struct GUID_ndr_buf){}.buf)];
246 const DATA_BLOB guid_blob = {.data = guid_buf,
247 .length = sizeof guid_buf};
249 generate_secret_buffer(guid_buf, sizeof guid_buf);
251 status = GUID_from_ndr_blob(&guid_blob, &root_key_id);
252 if (!NT_STATUS_IS_OK(status)) {
253 ret = ldb_operr(ldb);
259 struct ldb_dn *root_key_dn = NULL;
261 root_key_dn = samdb_gkdi_root_key_dn(ldb,
264 if (root_key_dn == NULL) {
265 ret = ldb_operr(ldb);
269 add_msg->dn = root_key_dn;
272 ret = dsdb_add(ldb, add_msg, 0);
277 *root_key_id_out = root_key_id;
278 *root_key_dn_out = talloc_steal(mem_ctx, add_msg->dn);
281 talloc_free(tmp_ctx);
286 * The PrivateKey, PublicKey, and SecretAgreement attributes are related to the
287 * public‐key functionality in GKDI. Samba doesn’t try to implement any of that,
288 * so we don’t bother looking at these attributes.
290 static const char *const root_key_attrs[] = {
293 "msKds-KDFAlgorithmID",
295 /* "msKds-PrivateKeyLength", */
296 /* "msKds-PublicKeyLength", */
298 /* "msKds-SecretAgreementAlgorithmID", */
299 /* "msKds-SecretAgreementParam", */
300 "msKds-UseStartTime",
306 * Create and return a new GKDI root key.
308 * This function goes unused.
310 int gkdi_new_root_key(TALLOC_CTX *mem_ctx,
311 struct ldb_context *const ldb,
312 const NTTIME current_time,
313 const NTTIME use_start_time,
314 struct GUID *const root_key_id_out,
315 const struct ldb_message **const root_key_out)
317 TALLOC_CTX *tmp_ctx = NULL;
318 struct ldb_dn *root_key_dn = NULL;
319 struct ldb_result *res = NULL;
320 int ret = LDB_SUCCESS;
322 *root_key_out = NULL;
324 tmp_ctx = talloc_new(mem_ctx);
325 if (tmp_ctx == NULL) {
330 ret = gkdi_create_root_key(tmp_ctx,
340 ret = dsdb_search_dn(
341 ldb, tmp_ctx, &res, root_key_dn, root_key_attrs, 0);
346 if (res->count != 1) {
347 ret = LDB_ERR_NO_SUCH_OBJECT;
351 *root_key_out = talloc_steal(mem_ctx, res->msgs[0]);
354 talloc_free(tmp_ctx);