2 * Unix SMB/CIFS implementation.
4 * Copyright (C) 2021-2022 Andreas Schneider <asn@samba.org>
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 <http://www.gnu.org/licenses/>.
28 #include "lib/replace/replace.h"
29 #include "lib/util/discard.h"
30 #include "lib/util/genrand.h"
31 #include "lib/util/data_blob.h"
32 #include "lib/util/talloc_stack.h"
33 #include "lib/crypto/gnutls_helpers.h"
34 #include "librpc/rpc/dcerpc_samr.h"
36 #include <gnutls/gnutls.h>
37 #include <gnutls/crypto.h>
39 #include "lib/crypto/gnutls_aead_aes_256_cbc_hmac_sha512.c"
41 /* The following hexdumps are from a Windows Server 2022 time trace */
42 static const uint8_t session_key[] = {
43 0x96, 0x17, 0x39, 0x9c, 0xa7, 0x54, 0x9e, 0x41,
44 0xc4, 0x79, 0x71, 0x4b, 0xa0, 0x89, 0x5b, 0x0a
47 static const uint8_t salt_data[] = {
48 0xac, 0x9c, 0xad, 0xcb, 0x66, 0xed, 0x2d, 0x05,
49 0x55, 0x13, 0x18, 0xa9, 0xa5, 0x6b, 0xf9, 0x6f
52 static const uint8_t plaintext_data[] = {
53 0x14, 0x00, 0x50, 0x00, 0x61, 0x00, 0x24, 0x00,
54 0x24, 0x00, 0x77, 0x00, 0x30, 0x00, 0x72, 0x00,
55 0x64, 0x00, 0x40, 0x00, 0x32, 0x00, 0xc2, 0x34,
56 0x7d, 0x21, 0x79, 0x05, 0xef, 0x88, 0xd7, 0x11,
57 0xec, 0xe2, 0xce, 0xb5, 0xd4, 0x4d, 0x64, 0x2d,
58 0x15, 0x79, 0x01, 0x39, 0xb8, 0xb9, 0x89, 0x5c,
59 0x4e, 0x71, 0xbd, 0xf0, 0x14, 0x0c, 0x87, 0x72,
60 0xa5, 0xfa, 0x90, 0xbe, 0x62, 0x55, 0xad, 0x7f,
61 0xe9, 0x7f, 0x0d, 0x20, 0x19, 0x3a, 0x76, 0xbe,
62 0xb2, 0x14, 0x6d, 0x5b, 0x25, 0x1c, 0x67, 0x3a,
63 0x23, 0x45, 0x1f, 0x7e, 0x36, 0xa0, 0x95, 0xb7,
64 0xa7, 0xb1, 0x33, 0xe1, 0xc4, 0xb6, 0xe6, 0x2d,
65 0xd8, 0x2f, 0xe7, 0xdf, 0x01, 0xe8, 0xba, 0x02,
66 0x54, 0x36, 0xe9, 0xb6, 0x5e, 0x00, 0x52, 0x9e,
67 0x64, 0x00, 0xcb, 0x3c, 0x6d, 0x05, 0x43, 0x7d,
68 0x01, 0x9c, 0x22, 0x18, 0x92, 0xe7, 0xa3, 0x55,
69 0x65, 0x6d, 0x2e, 0xa3, 0x53, 0x6e, 0xc0, 0x67,
70 0x26, 0xac, 0xaa, 0x98, 0xa4, 0xcb, 0xb4, 0x49,
71 0x13, 0x60, 0xd4, 0x33, 0x2c, 0x77, 0x58, 0x5e,
72 0x50, 0x45, 0xaa, 0x1e, 0x05, 0x15, 0x18, 0x59,
73 0x55, 0xca, 0x14, 0x37, 0x31, 0xac, 0x63, 0xfc,
74 0x63, 0xa8, 0x2a, 0xa9, 0x99, 0xec, 0x49, 0x87,
75 0x64, 0x1d, 0x4e, 0xdd, 0xa3, 0xd0, 0xdc, 0x08,
76 0x00, 0x17, 0xf4, 0x2f, 0x9c, 0x4a, 0x17, 0xc7,
77 0xbd, 0x30, 0xb7, 0x0e, 0x81, 0xe4, 0xd5, 0x94,
78 0x31, 0xff, 0xd6, 0xcc, 0xc6, 0xbb, 0x39, 0xcd,
79 0x72, 0xfe, 0xa6, 0x3d, 0x0d, 0x88, 0x68, 0x40,
80 0xf8, 0x51, 0x2b, 0xe6, 0xc9, 0xaa, 0x84, 0xf3,
81 0xf4, 0x6e, 0x55, 0x37, 0xbf, 0x5d, 0x87, 0xce,
82 0xa6, 0x80, 0x4f, 0x8f, 0x8f, 0x7b, 0xe8, 0x30,
83 0xc3, 0x2e, 0x24, 0xc7, 0x3e, 0xf1, 0x9f, 0xa6,
84 0x77, 0xca, 0x04, 0xbe, 0xb5, 0xe1, 0x40, 0x59,
85 0x43, 0xc5, 0x30, 0xc8, 0xe7, 0xbf, 0xab, 0xfa,
86 0x86, 0x62, 0xd9, 0x3a, 0x8e, 0xa9, 0x34, 0x73,
87 0x20, 0x7b, 0x61, 0x1b, 0x0e, 0xca, 0x98, 0xec,
88 0xa1, 0xc1, 0x78, 0xa9, 0xa7, 0x6c, 0x8c, 0xe3,
89 0x21, 0x7d, 0xb9, 0x90, 0xe2, 0x73, 0x1a, 0x99,
90 0x1d, 0x44, 0xa8, 0xd5, 0x7f, 0x0a, 0x59, 0x47,
91 0xd0, 0xf5, 0x6c, 0x14, 0xff, 0x4a, 0x29, 0x20,
92 0xb5, 0xfc, 0xe9, 0xf0, 0xa5, 0x35, 0x9e, 0x1c,
93 0xa1, 0x4c, 0xec, 0xb5, 0x7d, 0x2d, 0x27, 0xff,
94 0x7a, 0x42, 0x18, 0xb8, 0x53, 0x4e, 0xfb, 0xec,
95 0xb1, 0xc1, 0x65, 0x2d, 0xa4, 0x69, 0x85, 0x56,
96 0x61, 0x6d, 0x21, 0x66, 0x88, 0x31, 0xdf, 0xba,
97 0x28, 0xc6, 0x9a, 0xf8, 0xb7, 0xf6, 0x2a, 0x43,
98 0xba, 0x9b, 0x84, 0x14, 0xce, 0xa9, 0xc9, 0xf5,
99 0x85, 0x6f, 0x31, 0x89, 0x8d, 0xfc, 0x25, 0x2e,
100 0x98, 0x25, 0x5a, 0x03, 0xf0, 0xb8, 0x5d, 0x4a,
101 0xd4, 0x4c, 0xc8, 0x62, 0x4e, 0xeb, 0x07, 0xc8,
102 0x5c, 0x9e, 0x63, 0x30, 0xfe, 0x9f, 0x0f, 0x96,
103 0xd0, 0xd7, 0x70, 0xad, 0xcd, 0x84, 0xbc, 0x1e,
104 0x48, 0xa0, 0x20, 0x14, 0x10, 0xa4, 0xb1, 0x5b,
105 0x05, 0x36, 0x9a, 0x6d, 0xb0, 0x10, 0x98, 0xbd,
106 0x8d, 0xa2, 0xd1, 0xb2, 0xfa, 0x23, 0x37, 0xeb,
107 0xb0, 0x04, 0x53, 0xcb, 0xa1, 0xa9, 0xc4, 0x88,
108 0xdd, 0xf9, 0x80, 0xf5, 0xa9, 0xcd, 0x7b, 0xf8,
109 0x77, 0x0b, 0x19, 0x84, 0x4c, 0xef, 0x2c, 0x14,
110 0xa1, 0xdc, 0x9f, 0x2f, 0x41, 0xd0, 0xd0, 0x33,
111 0x29, 0x8a, 0xb9, 0x39, 0x7e, 0xc9, 0x7f, 0xe7,
112 0x63, 0x64, 0xa4, 0x7b, 0x4a, 0x6a, 0x33, 0xa7,
113 0xaa, 0xf6, 0xca, 0x98, 0xc4, 0x9b, 0x62, 0x5b,
114 0xcd, 0x53, 0x82, 0xbf, 0xf0, 0x0b, 0x9c, 0xe7,
115 0xb2, 0x44, 0x1b, 0x88, 0x71, 0x61, 0xa1, 0x36,
116 0x9e, 0x7a, 0x0a, 0x3c, 0x20, 0xd8, 0xff, 0xa1,
120 static const uint8_t expected_enc_key[] = {
121 0xd9, 0xb2, 0x8b, 0xa1, 0x15, 0x74, 0xf6, 0x5a,
122 0x73, 0xea, 0x82, 0xba, 0x99, 0x37, 0x54, 0x25,
123 0x1b, 0x27, 0x20, 0xaa, 0xa3, 0xf7, 0xd5, 0x23,
124 0x8f, 0x02, 0xe6, 0xe7, 0x21, 0x5b, 0xd2, 0xa9
127 static const uint8_t expected_mac_key[] = {
128 0x8a, 0x04, 0x46, 0x6d, 0x5e, 0xe6, 0x2d, 0xb8,
129 0x32, 0x9e, 0xab, 0xbe, 0xa4, 0x8b, 0x3f, 0x6c,
130 0x3c, 0x1c, 0xa1, 0xaa, 0xb8, 0xec, 0x9c, 0x43,
131 0xbc, 0x4b, 0x91, 0x35, 0x6f, 0x3a, 0xc4, 0xe2,
132 0x62, 0x9b, 0xe8, 0x12, 0x63, 0x73, 0x94, 0x2a,
133 0x59, 0x47, 0xfc, 0xd8, 0x78, 0x5d, 0x6d, 0x68,
134 0x1b, 0x9f, 0x35, 0x31, 0x90, 0x27, 0xc8, 0xab,
135 0x88, 0x8d, 0x80, 0xad, 0x7b, 0xea, 0xcd, 0xf5
138 static const uint8_t expected_auth_tag[] = {
139 0x0a, 0x7a, 0xaf, 0x9e, 0xc1, 0x6e, 0x03, 0x12,
140 0x51, 0x76, 0x04, 0xb2, 0x01, 0x17, 0xeb, 0x04,
141 0xf3, 0xdd, 0xe3, 0xa7, 0x90, 0xfd, 0xc0, 0xca,
142 0x96, 0x31, 0xbf, 0x30, 0x9e, 0xc5, 0x05, 0x5a,
143 0xbc, 0xa8, 0xc1, 0xba, 0x56, 0x8f, 0x97, 0x5a,
144 0x4e, 0x2a, 0x14, 0x0e, 0x4b, 0xf3, 0x6d, 0x9a,
145 0x2a, 0x6e, 0xc3, 0x5e, 0x9d, 0x51, 0x0a, 0xf6,
146 0xb2, 0x1b, 0xee, 0xe7, 0xf3, 0x09, 0x30, 0xc9,
149 static void torture_enc_key(void **state)
151 DATA_BLOB key = data_blob_const(session_key, sizeof(session_key));
152 uint8_t enc_key[32] = {0};
155 status = calculate_enc_key(&key, &samr_aes256_enc_key_salt, enc_key);
156 assert_true(NT_STATUS_IS_OK(status));
158 assert_memory_equal(expected_enc_key, enc_key, sizeof(enc_key));
161 static void torture_mac_key(void **state)
163 DATA_BLOB key = data_blob_const(session_key, sizeof(session_key));
164 uint8_t mac_key[64] = {0};
167 status = calculate_mac_key(&key, &samr_aes256_mac_key_salt, mac_key);
168 assert_true(NT_STATUS_IS_OK(status));
170 assert_memory_equal(expected_mac_key, mac_key, sizeof(mac_key));
173 static void torture_encrypt(void **state)
176 TALLOC_CTX *frame = talloc_stackframe();
178 .data = discard_const_p(uint8_t, session_key),
179 .length = sizeof(session_key),
181 const DATA_BLOB plaintext = {
182 .data = discard_const_p(uint8_t, plaintext_data),
183 .length = sizeof(plaintext_data),
186 .data = discard_const_p(uint8_t, salt_data),
187 .length = sizeof(salt_data),
190 uint8_t auth_tag[64] = {0};
192 assert_int_equal(iv.length, 16);
194 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(
198 &samr_aes256_enc_key_salt,
199 &samr_aes256_mac_key_salt,
203 assert_true(NT_STATUS_IS_OK(status));
204 assert_int_equal(ctext.length, 528);
205 assert_non_null(ctext.data);
207 assert_memory_equal(expected_auth_tag, auth_tag, sizeof(auth_tag));
212 static void torture_encrypt_decrypt(void **state)
215 TALLOC_CTX *frame = talloc_stackframe();
216 DATA_BLOB cek = data_blob_const(session_key, sizeof(session_key));
217 const DATA_BLOB plaintext =
218 data_blob_const(plaintext_data, sizeof(plaintext_data));
219 DATA_BLOB iv = data_blob_const(salt_data, sizeof(salt_data));
220 DATA_BLOB cipher_text;
221 uint8_t auth_tag[64] = {0};
222 DATA_BLOB plaintext_decrypted;
224 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(
228 &samr_aes256_enc_key_salt,
229 &samr_aes256_mac_key_salt,
233 assert_true(NT_STATUS_IS_OK(status));
234 assert_int_equal(cipher_text.length, 528);
235 assert_in_range(cipher_text.length,
237 plaintext.length + 16);
238 assert_non_null(cipher_text.data);
240 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_decrypt(
244 &samr_aes256_enc_key_salt,
245 &samr_aes256_mac_key_salt,
248 &plaintext_decrypted);
249 assert_true(NT_STATUS_IS_OK(status));
250 assert_non_null(plaintext_decrypted.data);
251 assert_int_equal(plaintext_decrypted.length, plaintext.length);
252 assert_memory_equal(plaintext_decrypted.data,
259 /* The following hexdumps are from a Windows Server 2022 time trace */
260 static uint8_t pbkdf2_nt_hash[] = {
261 0xf8, 0x48, 0x54, 0xde, 0xb8, 0x36, 0x10, 0x33,
262 0xca, 0xea, 0x5c, 0x95, 0x96, 0x66, 0x99, 0x38
265 static uint8_t pbkdf2_iv[] = {
266 0xd5, 0xbe, 0x4f, 0xd7, 0xb6, 0x85, 0xd1, 0xea,
267 0xfd, 0x3b, 0xf4, 0x29, 0x83, 0xce, 0x10, 0x44
270 static uint8_t expected_pbkdf2_derived_key[] = {
271 0xf1, 0xe6, 0xb2, 0x6a, 0x78, 0x28, 0x63, 0x05,
272 0x77, 0x38, 0xc9, 0x71, 0xd2, 0x05, 0x88, 0x58
275 static void torture_pbkdf2(void **state)
277 gnutls_datum_t nt_key = {
278 .data = pbkdf2_nt_hash,
279 .size = sizeof(pbkdf2_nt_hash),
281 gnutls_datum_t iv_datum = {
283 .size = sizeof(pbkdf2_iv),
285 uint64_t pbkdf2_iterations = 23533;
286 uint8_t derived_key[16] = {0};
289 rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
294 sizeof(derived_key));
295 assert_int_equal(rc, 0);
296 assert_memory_equal(derived_key,
297 expected_pbkdf2_derived_key,
298 sizeof(derived_key));
301 int main(int argc, char *argv[])
304 const struct CMUnitTest tests[] = {
305 cmocka_unit_test(torture_enc_key),
306 cmocka_unit_test(torture_mac_key),
307 cmocka_unit_test(torture_encrypt),
308 cmocka_unit_test(torture_encrypt_decrypt),
309 cmocka_unit_test(torture_pbkdf2),
313 cmocka_set_test_filter(argv[1]);
315 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
317 rc = cmocka_run_group_tests(tests, NULL, NULL);