]> git.saurik.com Git - apple/security.git/blob - protocol/SecProtocolTest.m
Security-59306.11.20.tar.gz
[apple/security.git] / protocol / SecProtocolTest.m
1 //
2 // SecProtocolTest.m
3 // SecureTransportTests
4 //
5
6 #import <AssertMacros.h>
7 #import <Foundation/Foundation.h>
8
9 #include <os/log.h>
10 #include <dlfcn.h>
11 #include <sys/param.h>
12
13 #import <XCTest/XCTest.h>
14
15 #import "SecProtocolConfiguration.h"
16 #import "SecProtocolPriv.h"
17 #import "SecProtocolInternal.h"
18
19 #import <nw/private.h> // Needed for the mock protocol
20
21 #define SEC_PROTOCOL_OPTIONS_VALIDATE(m, r) \
22 if (((void *)(m) == NULL) || ((size_t)(m) == 0)) { \
23 return (r); \
24 }
25
26 #define SEC_PROTOCOL_METADATA_VALIDATE(m, r) \
27 if (((void *)(m) == NULL) || ((size_t)(m) == 0)) { \
28 return (r); \
29 }
30
31 typedef struct mock_protocol {
32 struct nw_protocol protocol;
33 char *name;
34 } *mock_protocol_t;
35
36 static nw_protocol_t
37 _mock_protocol_create_extended(nw_protocol_identifier_const_t identifier,
38 nw_endpoint_t endpoint,
39 nw_parameters_t parameters)
40 {
41 mock_protocol_t handle = (mock_protocol_t)calloc(1, sizeof(struct mock_protocol));
42 if (handle == NULL) {
43 return NULL;
44 }
45
46 struct nw_protocol_callbacks *callbacks = (struct nw_protocol_callbacks *) malloc(sizeof(struct nw_protocol_callbacks));
47 memset(callbacks, 0, sizeof(struct nw_protocol_callbacks));
48
49 handle->protocol.callbacks = callbacks;
50 handle->protocol.handle = (void *)handle;
51
52 return &handle->protocol;
53 }
54
55 static bool
56 mock_protocol_register_extended(nw_protocol_identifier_const_t identifier,
57 nw_protocol_create_extended_f create_extended_function)
58 {
59 static void *libnetworkImage = NULL;
60 static dispatch_once_t onceToken;
61 static bool (*_nw_protocol_register_extended)(nw_protocol_identifier_const_t, nw_protocol_create_extended_f) = NULL;
62
63 dispatch_once(&onceToken, ^{
64 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
65 if (NULL != libnetworkImage) {
66 _nw_protocol_register_extended = (__typeof(_nw_protocol_register_extended))dlsym(libnetworkImage, "nw_protocol_register_extended");
67 if (NULL == _nw_protocol_register_extended) {
68 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_register_extended");
69 }
70 } else {
71 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
72 }
73 });
74
75 if (_nw_protocol_register_extended == NULL) {
76 return false;
77 }
78
79 return _nw_protocol_register_extended(identifier, create_extended_function);
80 }
81
82 static nw_protocol_identifier_t
83 _mock_protocol_identifier(const char *name, size_t name_len)
84 {
85 static struct nw_protocol_identifier mock_identifer = {};
86 static dispatch_once_t onceToken = 0;
87 dispatch_once(&onceToken, ^{
88 memset(&mock_identifer, 0, sizeof(mock_identifer));
89
90 strlcpy((char *)mock_identifer.name, name, name_len);
91
92 mock_identifer.level = nw_protocol_level_application;
93 mock_identifer.mapping = nw_protocol_mapping_one_to_one;
94
95 mock_protocol_register_extended(&mock_identifer, _mock_protocol_create_extended);
96 });
97
98 return &mock_identifer;
99 }
100
101 static void * _Nullable
102 mock_protocol_allocate_metadata(__unused nw_protocol_definition_t definition)
103 {
104 return calloc(1, sizeof(struct sec_protocol_metadata_content));
105 }
106
107 static void
108 mock_protocol_deallocate_metadata(__unused nw_protocol_definition_t definition, void *metadata)
109 {
110 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)metadata;
111 if (content) {
112 // pass
113 }
114 free(content);
115 }
116
117 static void
118 mock_protocol_set_metadata_allocator(nw_protocol_definition_t definition, nw_protocol_definition_allocate_f allocator, nw_protocol_definition_deallocate_f deallocator)
119 {
120 static void *libnetworkImage = NULL;
121 static dispatch_once_t onceToken;
122 static void (*_nw_protocol_definition_set_metadata_allocator)(nw_protocol_definition_t, nw_protocol_definition_allocate_f, nw_protocol_definition_deallocate_f) = NULL;
123
124 dispatch_once(&onceToken, ^{
125 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
126 if (NULL != libnetworkImage) {
127 _nw_protocol_definition_set_metadata_allocator = (__typeof(_nw_protocol_definition_set_metadata_allocator))dlsym(libnetworkImage, "nw_protocol_definition_set_metadata_allocator");
128 if (NULL == _nw_protocol_definition_set_metadata_allocator) {
129 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_definition_set_metadata_allocator");
130 }
131 } else {
132 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
133 }
134 });
135
136 if (_nw_protocol_definition_set_metadata_allocator == NULL) {
137 return;
138 }
139
140 _nw_protocol_definition_set_metadata_allocator(definition, allocator, deallocator);
141 }
142
143 static void * _Nullable
144 mock_protocol_copy_options(__unused nw_protocol_definition_t definition, void *options)
145 {
146 void *new_options = calloc(1, sizeof(struct sec_protocol_options_content));
147
148 sec_protocol_options_content_t copy = (sec_protocol_options_content_t)new_options;
149 sec_protocol_options_content_t original = (sec_protocol_options_content_t)options;
150
151 copy->min_version = original->min_version;
152 copy->max_version = original->max_version;
153 copy->disable_sni = original->disable_sni;
154 copy->enable_fallback_attempt = original->enable_fallback_attempt;
155 copy->enable_false_start = original->enable_false_start;
156 copy->enable_tickets = original->enable_tickets;
157 copy->enable_sct = original->enable_sct;
158 copy->enable_ocsp = original->enable_ocsp;
159 copy->enable_resumption = original->enable_resumption;
160 copy->enable_renegotiation = original->enable_renegotiation;
161 copy->enable_early_data = original->enable_early_data;
162
163 if (original->server_name) {
164 copy->server_name = strdup(original->server_name);
165 }
166 if (original->identity) {
167 copy->identity = original->identity;
168 }
169 if (original->application_protocols) {
170 copy->application_protocols = xpc_copy(original->application_protocols);
171 }
172 if (original->ciphersuites) {
173 copy->ciphersuites = xpc_copy(original->ciphersuites);
174 }
175 if (original->dh_params) {
176 copy->dh_params = original->dh_params;
177 }
178 if (original->key_update_block) {
179 copy->key_update_block = original->key_update_block;
180 copy->key_update_queue = original->key_update_queue;
181 }
182 if (original->challenge_block) {
183 copy->challenge_block = original->challenge_block;
184 copy->challenge_queue = original->challenge_queue;
185 }
186 if (original->verify_block) {
187 copy->verify_block = original->verify_block;
188 copy->verify_queue = original->verify_queue;
189 }
190 if (original->session_state) {
191 copy->session_state = original->session_state;
192 }
193 if (original->session_update_block) {
194 copy->session_update_block = original->session_update_block;
195 copy->session_update_queue = original->session_update_queue;
196 }
197 if (original->pre_shared_keys) {
198 copy->pre_shared_keys = xpc_copy(original->pre_shared_keys);
199 }
200
201 return new_options;
202 }
203
204 static void * _Nullable
205 mock_protocol_allocate_options(__unused nw_protocol_definition_t definition)
206 {
207 return calloc(1, sizeof(struct sec_protocol_options_content));
208 }
209
210 static void
211 mock_protocol_deallocate_options(__unused nw_protocol_definition_t definition, void *options)
212 {
213 sec_protocol_options_content_t content = (sec_protocol_options_content_t)options;
214 if (content) {
215 // pass
216 }
217 free(content);
218 }
219
220 static void
221 mock_protocol_set_options_allocator(nw_protocol_definition_t definition,
222 nw_protocol_definition_allocate_f allocate_function,
223 nw_protocol_definition_copy_f copy_function,
224 nw_protocol_definition_deallocate_f deallocate_function)
225 {
226 static void *libnetworkImage = NULL;
227 static dispatch_once_t onceToken;
228 static void (*_nw_protocol_definition_set_options_allocator)(nw_protocol_definition_t, nw_protocol_definition_allocate_f, nw_protocol_definition_copy_f, nw_protocol_definition_deallocate_f) = NULL;
229
230 dispatch_once(&onceToken, ^{
231 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
232 if (NULL != libnetworkImage) {
233 _nw_protocol_definition_set_options_allocator = (__typeof(_nw_protocol_definition_set_options_allocator))dlsym(libnetworkImage, "nw_protocol_definition_set_options_allocator");
234 if (NULL == _nw_protocol_definition_set_options_allocator) {
235 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_definition_set_options_allocator");
236 }
237 } else {
238 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
239 }
240 });
241
242 if (_nw_protocol_definition_set_options_allocator == NULL) {
243 return;
244 }
245
246 _nw_protocol_definition_set_options_allocator(definition, allocate_function, copy_function, deallocate_function);
247 }
248
249 static nw_protocol_definition_t
250 mock_protocol_definition_create_with_identifier(nw_protocol_identifier_const_t identifier)
251 {
252 static void *libnetworkImage = NULL;
253 static dispatch_once_t onceToken;
254 static nw_protocol_definition_t (*_nw_protocol_definition_create_with_identifier)(nw_protocol_identifier_const_t) = NULL;
255
256 dispatch_once(&onceToken, ^{
257 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
258 if (NULL != libnetworkImage) {
259 _nw_protocol_definition_create_with_identifier = (__typeof(_nw_protocol_definition_create_with_identifier))dlsym(libnetworkImage, "nw_protocol_definition_create_with_identifier");
260 if (NULL == _nw_protocol_definition_create_with_identifier) {
261 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_definition_create_with_identifier");
262 }
263 } else {
264 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
265 }
266 });
267
268 if (_nw_protocol_definition_create_with_identifier == NULL) {
269 return NULL;
270 }
271
272 return _nw_protocol_definition_create_with_identifier(identifier);
273 }
274
275 static nw_protocol_definition_t
276 mock_protocol_copy_definition(void)
277 {
278 static nw_protocol_definition_t definition = NULL;
279 static dispatch_once_t onceToken;
280 dispatch_once(&onceToken, ^{
281 const char *mock_protocol_name = "secProtocolTestMockProtocol";
282 definition = mock_protocol_definition_create_with_identifier(_mock_protocol_identifier(mock_protocol_name, strlen(mock_protocol_name)));
283 mock_protocol_set_options_allocator(definition,
284 mock_protocol_allocate_options,
285 mock_protocol_copy_options,
286 mock_protocol_deallocate_options);
287 mock_protocol_set_metadata_allocator(definition,
288 mock_protocol_allocate_metadata,
289 mock_protocol_deallocate_metadata);
290
291 });
292
293 return definition;
294 }
295
296 @interface SecProtocolTest : XCTestCase
297 @property nw_protocol_t mock_protocol;
298 @end
299
300 @implementation SecProtocolTest
301
302 - (void)setUp {
303 [super setUp];
304 }
305
306 - (void)tearDown {
307 [super tearDown];
308 }
309
310 - (sec_protocol_options_t)create_sec_protocol_options {
311 static void *libnetworkImage = NULL;
312 static dispatch_once_t onceToken;
313
314 static sec_protocol_options_t (*_nw_protocol_create_options)(nw_protocol_definition_t) = NULL;
315
316 dispatch_once(&onceToken, ^{
317 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
318 if (NULL != libnetworkImage) {
319 _nw_protocol_create_options = (__typeof(_nw_protocol_create_options))dlsym(libnetworkImage, "nw_protocol_create_options");
320 if (NULL == _nw_protocol_create_options) {
321 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork _nw_protocol_create_options");
322 }
323 } else {
324 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
325 }
326 });
327
328 if (_nw_protocol_create_options == NULL) {
329 return nil;
330 }
331
332 return (sec_protocol_options_t)_nw_protocol_create_options(mock_protocol_copy_definition());
333 }
334
335 - (sec_protocol_metadata_t)create_sec_protocol_metadata {
336 uuid_t identifier;
337 uuid_generate(identifier);
338
339 static void *libnetworkImage = NULL;
340 static dispatch_once_t onceToken;
341 static sec_protocol_metadata_t (*_nw_protocol_metadata_create)(nw_protocol_definition_t, _Nonnull uuid_t) = NULL;
342
343 dispatch_once(&onceToken, ^{
344 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
345 if (NULL != libnetworkImage) {
346 _nw_protocol_metadata_create = (__typeof(_nw_protocol_metadata_create))dlsym(libnetworkImage, "nw_protocol_metadata_create");
347 if (NULL == _nw_protocol_metadata_create) {
348 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_metadata_create");
349 }
350 } else {
351 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
352 }
353 });
354
355 if (_nw_protocol_metadata_create == NULL) {
356 return nil;
357 }
358
359 return (sec_protocol_metadata_t)_nw_protocol_metadata_create(mock_protocol_copy_definition(), identifier);
360 }
361
362 - (void)test_sec_protocol_metadata_get_connection_strength_tls12 {
363 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
364
365 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
366 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
367 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
368
369 content->negotiated_ciphersuite = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
370 #pragma clang diagnostic push
371 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
372 content->negotiated_protocol_version = kTLSProtocol12;
373 #pragma clang diagnostic pop
374
375 return true;
376 });
377
378 XCTAssertTrue(SSLConnectionStrengthStrong == sec_protocol_metadata_get_connection_strength(metadata),
379 "Expected SSLConnectionStrengthStrong for TLS 1.2 with a strong ciphersuite, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
380 }
381
382 - (void)test_sec_protocol_metadata_get_connection_strength_tls12_weak_ciphersuite {
383 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
384 if (metadata) {
385 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
386 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
387 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
388
389 content->negotiated_ciphersuite = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
390 #pragma clang diagnostic push
391 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
392 content->negotiated_protocol_version = kTLSProtocol12;
393 #pragma clang diagnostic pop
394
395 return true;
396 });
397
398 XCTAssertTrue(SSLConnectionStrengthWeak == sec_protocol_metadata_get_connection_strength(metadata),
399 "Expected SSLConnectionStrengthWeak for TLS 1.2 with a weak ciphersuite, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
400 }
401 }
402
403 - (void)test_sec_protocol_metadata_get_connection_strength_tls11 {
404 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
405 if (metadata) {
406 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
407 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
408 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
409
410 content->negotiated_ciphersuite = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
411 #pragma clang diagnostic push
412 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
413 content->negotiated_protocol_version = kTLSProtocol11;
414 #pragma clang diagnostic pop
415
416 return true;
417 });
418
419 XCTAssertTrue(SSLConnectionStrengthWeak == sec_protocol_metadata_get_connection_strength(metadata),
420 "Expected SSLConnectionStrengthWeak for TLS 1.1, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
421 }
422 }
423
424 - (void)test_sec_protocol_metadata_get_connection_strength_tls10 {
425 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
426 if (metadata) {
427 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
428 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
429 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
430
431 content->negotiated_ciphersuite = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
432 #pragma clang diagnostic push
433 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
434 content->negotiated_protocol_version = kTLSProtocol1;
435 #pragma clang diagnostic pop
436
437 return true;
438 });
439
440 XCTAssertTrue(SSLConnectionStrengthWeak == sec_protocol_metadata_get_connection_strength(metadata),
441 "Expected SSLConnectionStrengthWeak for TLS 1.0, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
442 }
443 }
444
445 - (void)test_sec_protocol_metadata_get_connection_strength_sslv3_strong_ciphersuite {
446 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
447 if (metadata) {
448 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
449 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
450 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
451
452 content->negotiated_ciphersuite = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; // This can be anything -- we downgrade based on the version here.
453 #pragma clang diagnostic push
454 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
455 content->negotiated_protocol_version = kSSLProtocol3;
456 #pragma clang diagnostic pop
457
458 return true;
459 });
460
461 XCTAssertTrue(SSLConnectionStrengthNonsecure == sec_protocol_metadata_get_connection_strength(metadata),
462 "Expected SSLConnectionStrengthNonsecure for SSL 3.0, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
463 }
464 }
465
466 - (void)test_sec_protocol_metadata_get_connection_strength_sslv3_weak_ciphersuite {
467 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
468 if (metadata) {
469 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
470 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
471 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
472
473 content->negotiated_ciphersuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
474 #pragma clang diagnostic push
475 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
476 content->negotiated_protocol_version = kSSLProtocol3;
477 #pragma clang diagnostic pop
478
479 return true;
480 });
481
482 XCTAssertTrue(SSLConnectionStrengthNonsecure == sec_protocol_metadata_get_connection_strength(metadata),
483 "Expected SSLConnectionStrengthNonsecure for SSL 3.0, got %d", (int)sec_protocol_metadata_get_connection_strength(metadata));
484 }
485 }
486
487 static size_t
488 _sec_protocol_dispatch_data_copyout(dispatch_data_t data, void *destination, size_t maxlen)
489 {
490 __block size_t copied = 0;
491 __block uint8_t *buffer = (uint8_t *)destination;
492
493 if (data) {
494 dispatch_data_apply(data, ^bool(__unused dispatch_data_t region, __unused size_t offset, const void *dbuffer, size_t size) {
495 size_t consumed = MIN(maxlen - copied, size);
496 if (consumed) {
497 memcpy(&buffer[copied], dbuffer, consumed);
498 copied += consumed;
499 }
500
501 return copied < maxlen;
502 });
503 }
504
505 return copied;
506 }
507
508 static dispatch_data_t
509 _sec_protocol_test_metadata_session_exporter(void *handle)
510 {
511 if (handle == NULL) {
512 return nil;
513 }
514
515 const char *received_handle = (const char *)handle;
516 dispatch_data_t serialized_session = dispatch_data_create(received_handle, strlen(received_handle), NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
517 return serialized_session;
518 }
519
520 - (void)test_sec_protocol_register_session_update {
521 sec_protocol_options_t options = [self create_sec_protocol_options];
522 dispatch_queue_t test_queue = dispatch_queue_create("test_sec_protocol_register_session_update", NULL);
523 __block bool session_updated = false;
524
525 __block dispatch_data_t serialized_session_copy = nil;
526 sec_protocol_session_update_t update_block = ^(sec_protocol_metadata_t metadata) {
527 session_updated = true;
528 serialized_session_copy = sec_protocol_metadata_copy_serialized_session(metadata);
529 };
530
531 sec_protocol_options_set_session_update_block(options, update_block, test_queue);
532
533 const char *metadata_context_handle = "context handle";
534
535 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
536 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
537 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
538 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
539
540 content->session_exporter_context = (void *)metadata_context_handle;
541 content->session_exporter_function = _sec_protocol_test_metadata_session_exporter;
542
543 return true;
544 });
545
546 update_block(metadata);
547
548 XCTAssertTrue(session_updated, "Expected session update callback block to fire");
549 XCTAssertNotNil(serialized_session_copy, "Expected non-nil serialized session");
550
551 if (serialized_session_copy) {
552 size_t data_size = dispatch_data_get_size(serialized_session_copy);
553 uint8_t *session_copy_buffer = (uint8_t *)malloc(data_size);
554
555 (void)_sec_protocol_dispatch_data_copyout(serialized_session_copy, session_copy_buffer, data_size);
556 XCTAssertTrue(data_size == strlen(metadata_context_handle));
557 XCTAssertTrue(memcmp(session_copy_buffer, metadata_context_handle, data_size) == 0);
558
559 free(session_copy_buffer);
560 }
561 }
562
563 #define SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR "stack_error"
564 #define SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE "cipher_name"
565
566 - (void)test_sec_protocol_metadata_serialize_success {
567 sec_protocol_options_t options = [self create_sec_protocol_options];
568 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
569 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
570 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
571 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
572
573 content->failure = false;
574 content->stack_error = 0xDEAD;
575 content->negotiated_ciphersuite = TLS_AES_256_GCM_SHA384;
576 return true;
577 });
578
579 xpc_object_t dictionary = sec_protocol_metadata_serialize_with_options(metadata, options);
580 XCTAssertTrue(dictionary != NULL);
581 XCTAssertTrue(xpc_dictionary_get_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR) == 0x00,
582 "Expected 0x%x, got 0x%llx", 0x00, xpc_dictionary_get_int64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR));
583 XCTAssertTrue(xpc_dictionary_get_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE) == TLS_AES_256_GCM_SHA384,
584 "Expected 0x%x, got 0x%llx", TLS_AES_256_GCM_SHA384, xpc_dictionary_get_int64(dictionary, SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE));
585 }
586
587 - (void)test_sec_protocol_metadata_serialize_failure {
588 sec_protocol_options_t options = [self create_sec_protocol_options];
589 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
590 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
591 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
592 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
593
594 content->failure = true;
595 content->stack_error = 0xDEAD;
596 content->negotiated_ciphersuite = TLS_AES_256_GCM_SHA384;
597 return true;
598 });
599
600 xpc_object_t dictionary = sec_protocol_metadata_serialize_with_options(metadata, options);
601 XCTAssertTrue(dictionary != NULL);
602 XCTAssertTrue(xpc_dictionary_get_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR) == 0xDEAD,
603 "Expected 0x%x, got 0x%llx", 0xDEAD, xpc_dictionary_get_int64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR));
604 XCTAssertTrue(xpc_dictionary_get_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE) == 0x00,
605 "Expected 0x%x, got 0x%llx", 0x00, xpc_dictionary_get_int64(dictionary, SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE));
606 }
607
608 - (void)test_sec_protocol_options_set_quic_transport_parameters {
609 uint8_t parameters_buffer[] = {0x00, 0x01, 0x02, 0x03};
610 uint8_t expected_parameters_buffer[sizeof(parameters_buffer)] = {0};
611
612 __block size_t parameters_len = sizeof(parameters_buffer);
613 __block uint8_t *parameters = parameters_buffer;
614 __block uint8_t *expected_parameters = expected_parameters_buffer;
615 __block dispatch_data_t parameters_data = dispatch_data_create(parameters, sizeof(parameters_buffer), NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
616
617 sec_protocol_options_t options = [self create_sec_protocol_options];
618 sec_protocol_options_set_quic_transport_parameters(options, parameters_data);
619
620 bool result = sec_protocol_options_access_handle(options, ^bool(void *handle) {
621 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
622 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
623
624 if (content->quic_transport_parameters) {
625 dispatch_data_t actual_parameters = content->quic_transport_parameters;
626 size_t data_len = _sec_protocol_dispatch_data_copyout(actual_parameters, expected_parameters, parameters_len);
627
628 if (data_len == parameters_len) {
629 return 0 == memcmp(parameters, expected_parameters, parameters_len);
630 }
631 }
632
633 return false;
634 });
635
636 XCTAssertTrue(result);
637 }
638
639 - (void)test_sec_protocol_metadata_copy_quic_transport_parameters {
640 uint8_t parameters_buffer[] = {0x00, 0x01, 0x02, 0x03};
641 uint8_t expected_parameters_buffer[sizeof(parameters_buffer)] = {0};
642
643 __block size_t parameters_len = sizeof(parameters_buffer);
644 __block uint8_t *parameters = parameters_buffer;
645 __block uint8_t *expected_parameters = expected_parameters_buffer;
646 __block dispatch_data_t parameters_data = dispatch_data_create(parameters, sizeof(parameters_buffer), NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
647
648 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
649 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
650 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
651 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
652
653 content->quic_transport_parameters = parameters_data;
654 return true;
655 });
656
657 dispatch_data_t actual_parameters = sec_protocol_metadata_copy_quic_transport_parameters(metadata);
658 size_t data_len = _sec_protocol_dispatch_data_copyout(actual_parameters, expected_parameters, parameters_len);
659
660 bool result = false;
661 if (data_len == parameters_len) {
662 result = 0 == memcmp(parameters, expected_parameters, parameters_len);
663 }
664 XCTAssertTrue(result);
665 }
666
667 - (void)test_sec_protocol_options_set_tls_encryption_secret_update_block {
668 void (^update_block)(sec_protocol_tls_encryption_level_t, bool, dispatch_data_t) = ^(__unused sec_protocol_tls_encryption_level_t level, __unused bool is_write, __unused dispatch_data_t secret) {
669 // pass
670 };
671
672 dispatch_queue_t update_queue = dispatch_queue_create("test_sec_protocol_options_set_tls_encryption_secret_update_block_queue", DISPATCH_QUEUE_SERIAL);
673
674 sec_protocol_options_t options = [self create_sec_protocol_options];
675 sec_protocol_options_set_tls_encryption_secret_update_block(options, update_block, update_queue);
676 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
677 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
678 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
679 XCTAssertTrue(content->tls_secret_update_block == update_block);
680 XCTAssertTrue(content->tls_secret_update_queue != nil);
681 return false;
682 });
683 }
684
685 - (void)test_sec_protocol_options_set_local_certificates {
686 sec_protocol_options_t options = [self create_sec_protocol_options];
687
688 sec_array_t certificates = sec_array_create();
689 sec_protocol_options_set_local_certificates(options, certificates);
690
691 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
692 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
693 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
694 XCTAssertTrue(content->certificates == certificates);
695 return true;
696 });
697 }
698
699 - (void)test_sec_protocol_options_set_private_key_blocks {
700 sec_protocol_options_t options = [self create_sec_protocol_options];
701
702 void (^sign_block)(uint16_t algorithm, dispatch_data_t, sec_protocol_private_key_complete_t) = ^(__unused uint16_t algorithm, __unused dispatch_data_t input, __unused sec_protocol_private_key_complete_t complete) {
703 // pass
704 };
705 void (^decrypt_block)(dispatch_data_t, sec_protocol_private_key_complete_t) = ^(__unused dispatch_data_t input, __unused sec_protocol_private_key_complete_t complete) {
706 // pass
707 };
708 dispatch_queue_t queue = dispatch_queue_create("private_key_operation_queue", DISPATCH_QUEUE_SERIAL);
709
710 sec_protocol_options_set_private_key_blocks(options, sign_block, decrypt_block, queue);
711 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
712 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
713 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
714 XCTAssertTrue(content->private_key_sign_block == sign_block);
715 XCTAssertTrue(content->private_key_decrypt_block == decrypt_block);
716 XCTAssertTrue(content->private_key_queue == queue);
717 return true;
718 });
719 }
720
721 - (void)test_sec_protocol_options_set_tls_certificate_compression_enabled {
722 sec_protocol_options_t options = [self create_sec_protocol_options];
723
724 sec_protocol_options_set_tls_certificate_compression_enabled(options, true);
725 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
726 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
727 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
728 XCTAssertTrue(content->certificate_compression_enabled);
729 return true;
730 });
731 }
732
733 - (void)test_sec_protocol_options_are_equal {
734 sec_protocol_options_t optionsA = [self create_sec_protocol_options];
735 sec_protocol_options_t optionsB = [self create_sec_protocol_options];
736
737 #pragma clang diagnostic push
738 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
739 sec_protocol_options_set_tls_min_version(optionsA, kTLSProtocol13);
740 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
741 sec_protocol_options_set_tls_min_version(optionsB, kTLSProtocol13);
742 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
743
744 sec_protocol_options_set_tls_max_version(optionsA, kTLSProtocol13);
745 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
746 sec_protocol_options_set_tls_max_version(optionsB, kTLSProtocol13);
747 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
748 #pragma clang diagnostic pop
749
750 sec_protocol_options_set_tls_sni_disabled(optionsA, true);
751 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
752 sec_protocol_options_set_tls_sni_disabled(optionsB, false);
753 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
754 sec_protocol_options_set_tls_sni_disabled(optionsB, true);
755 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
756
757 sec_protocol_options_set_tls_is_fallback_attempt(optionsA, true);
758 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
759 sec_protocol_options_set_tls_is_fallback_attempt(optionsB, false);
760 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
761 sec_protocol_options_set_tls_is_fallback_attempt(optionsB, true);
762 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
763
764 sec_protocol_options_set_tls_false_start_enabled(optionsA, true);
765 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
766 sec_protocol_options_set_tls_false_start_enabled(optionsB, false);
767 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
768 sec_protocol_options_set_tls_false_start_enabled(optionsB, true);
769 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
770
771 sec_protocol_options_set_tls_tickets_enabled(optionsA, true);
772 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
773 sec_protocol_options_set_tls_tickets_enabled(optionsB, false);
774 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
775 sec_protocol_options_set_tls_tickets_enabled(optionsB, true);
776 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
777
778 sec_protocol_options_set_tls_sct_enabled(optionsA, true);
779 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
780 sec_protocol_options_set_tls_sct_enabled(optionsB, false);
781 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
782 sec_protocol_options_set_tls_sct_enabled(optionsB, true);
783 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
784
785 sec_protocol_options_set_tls_ocsp_enabled(optionsA, true);
786 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
787 sec_protocol_options_set_tls_ocsp_enabled(optionsB, false);
788 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
789 sec_protocol_options_set_tls_ocsp_enabled(optionsB, true);
790 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
791
792 sec_protocol_options_set_tls_resumption_enabled(optionsA, true);
793 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
794 sec_protocol_options_set_tls_resumption_enabled(optionsB, false);
795 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
796 sec_protocol_options_set_tls_resumption_enabled(optionsB, true);
797 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
798
799 sec_protocol_options_set_tls_renegotiation_enabled(optionsA, true);
800 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
801 sec_protocol_options_set_tls_renegotiation_enabled(optionsB, false);
802 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
803 sec_protocol_options_set_tls_renegotiation_enabled(optionsB, true);
804 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
805
806 sec_protocol_options_set_tls_grease_enabled(optionsA, true);
807 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
808 sec_protocol_options_set_tls_grease_enabled(optionsB, false);
809 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
810 sec_protocol_options_set_tls_grease_enabled(optionsB, true);
811 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
812
813 sec_protocol_options_set_tls_delegated_credentials_enabled(optionsA, true);
814 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
815 sec_protocol_options_set_tls_delegated_credentials_enabled(optionsB, false);
816 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
817 sec_protocol_options_set_tls_delegated_credentials_enabled(optionsB, true);
818 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
819
820 sec_protocol_options_set_eddsa_enabled(optionsA, true);
821 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
822 sec_protocol_options_set_eddsa_enabled(optionsB, false);
823 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
824 sec_protocol_options_set_eddsa_enabled(optionsB, true);
825 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
826
827 sec_protocol_options_set_tls_early_data_enabled(optionsA, true);
828 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
829 sec_protocol_options_set_tls_early_data_enabled(optionsB, false);
830 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
831 sec_protocol_options_set_tls_early_data_enabled(optionsB, true);
832 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
833
834 sec_protocol_options_set_tls_certificate_compression_enabled(optionsA, true);
835 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
836 sec_protocol_options_set_tls_certificate_compression_enabled(optionsB, false);
837 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
838 sec_protocol_options_set_tls_certificate_compression_enabled(optionsB, true);
839 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
840
841 const char *server_nameA = "localhost";
842 const char *server_nameB = "apple.com";
843 sec_protocol_options_set_tls_server_name(optionsA, server_nameA);
844 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
845 sec_protocol_options_set_tls_server_name(optionsB, server_nameB);
846 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
847 sec_protocol_options_set_tls_server_name(optionsB, server_nameA);
848 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
849
850 uint8_t quic_parameters_buffer[] = {0x00, 0x01, 0x02, 0x03};
851 dispatch_data_t quic_parameters = dispatch_data_create(quic_parameters_buffer, sizeof(quic_parameters_buffer), nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
852 sec_protocol_options_set_quic_transport_parameters(optionsA, quic_parameters);
853 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
854 sec_protocol_options_set_quic_transport_parameters(optionsB, quic_parameters);
855 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
856
857 sec_protocol_options_append_tls_ciphersuite(optionsA, 1337);
858 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
859 sec_protocol_options_append_tls_ciphersuite(optionsB, 1337);
860 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
861
862 const char *application_protocolA = "h2";
863 const char *application_protocolB = "h3";
864 sec_protocol_options_add_tls_application_protocol(optionsA, application_protocolA);
865 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
866 sec_protocol_options_add_tls_application_protocol(optionsB, application_protocolB);
867 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
868
869 sec_protocol_options_append_tls_ciphersuite(optionsB, 7331);
870 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
871 }
872
873 - (void)test_sec_protocol_options_set_tls_server_name {
874 sec_protocol_options_t optionsA = [self create_sec_protocol_options];
875 sec_protocol_options_t optionsB = [self create_sec_protocol_options];
876
877 const char *server_nameA = "apple.com";
878 const char *server_nameB = "127.0.0.1";
879 const char *server_nameC = "example.com";
880
881 /*
882 * Empty options should be equal.
883 */
884 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
885
886 /*
887 * Set the name in optionsA.
888 * Options A, B should now be different.
889 */
890 sec_protocol_options_set_tls_server_name(optionsA, server_nameA);
891 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
892
893 /*
894 * Set the name to nameA in optionsB.
895 * Options A, B should now be equal.
896 */
897 sec_protocol_options_set_tls_server_name(optionsB, server_nameA);
898 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
899
900 /*
901 * Try to set the name to nameB in optionsB.
902 * It should fail since nameB is invalid.
903 * Options A, B should still be equal.
904 */
905 sec_protocol_options_set_tls_server_name(optionsB, server_nameB);
906 XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB));
907
908 /*
909 * Change the current name in B.
910 * Comparison should fail.
911 */
912 sec_protocol_options_set_tls_server_name(optionsB, server_nameC);
913 XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB));
914 }
915
916 - (void)test_sec_protocol_options_create_and_import_config {
917 sec_protocol_options_t options = [self create_sec_protocol_options];
918 sec_protocol_options_t imported_options = [self create_sec_protocol_options];
919
920 sec_protocol_options_set_min_tls_protocol_version(options, tls_protocol_version_TLSv13);
921 sec_protocol_options_set_tls_early_data_enabled(options, true);
922 xpc_object_t config = sec_protocol_options_create_config(options);
923 XCTAssertTrue(config != NULL);
924 if (config != NULL) {
925 sec_protocol_options_apply_config(imported_options, config);
926 XCTAssertTrue(sec_protocol_options_are_equal(options, imported_options));
927 }
928 }
929
930 - (void)test_sec_protocol_options_matches_full_config {
931 sec_protocol_options_t options = [self create_sec_protocol_options];
932
933 sec_protocol_options_set_min_tls_protocol_version(options, tls_protocol_version_TLSv13);
934 sec_protocol_options_set_tls_early_data_enabled(options, true);
935 xpc_object_t config = sec_protocol_options_create_config(options);
936 XCTAssertTrue(config != NULL);
937 if (config != NULL) {
938 XCTAssertTrue(sec_protocol_options_matches_config(options, config));
939 }
940 }
941
942 - (void)test_sec_protocol_options_matches_partial_config {
943 sec_protocol_options_t options = [self create_sec_protocol_options];
944 sec_protocol_options_set_tls_resumption_enabled(options, true);
945
946 xpc_object_t config = sec_protocol_options_create_config(options);
947 XCTAssertTrue(config != NULL);
948 if (config != NULL) {
949 // Drop one key from the config, and make sure that the result still matches
950 __block const char *enable_resumption_key = "enable_resumption";
951 xpc_object_t trimmed_config = xpc_dictionary_create(NULL, NULL, 0);
952 xpc_dictionary_apply(config, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
953 if (strncmp(key, enable_resumption_key, strlen(enable_resumption_key)) != 0) {
954 xpc_dictionary_set_value(trimmed_config, key, value);
955 }
956 return true;
957 });
958 XCTAssertTrue(sec_protocol_options_matches_config(options, trimmed_config));
959 }
960 }
961
962 - (void)test_sec_protocol_options_matches_config_with_mismatch {
963 sec_protocol_options_t options = [self create_sec_protocol_options];
964
965 __block bool enable_resumption = true;
966 sec_protocol_options_set_tls_resumption_enabled(options, enable_resumption);
967
968 xpc_object_t config = sec_protocol_options_create_config(options);
969 XCTAssertTrue(config != NULL);
970 if (config != NULL) {
971 // Flip a value in the config, and expect the match to fail
972 __block const char *enable_resumption_key = "enable_resumption";
973 xpc_object_t mismatched_config = xpc_dictionary_create(NULL, NULL, 0);
974 xpc_dictionary_apply(config, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
975 if (strncmp(key, enable_resumption_key, strlen(enable_resumption_key)) != 0) {
976 xpc_dictionary_set_value(mismatched_config, key, value);
977 } else {
978 xpc_dictionary_set_bool(mismatched_config, key, !enable_resumption);
979 }
980 return true;
981 });
982 XCTAssertFalse(sec_protocol_options_matches_config(options, mismatched_config));
983 }
984 }
985
986 - (void)test_sec_protocol_options_matches_config_with_mismatch_ciphersuites {
987 sec_protocol_options_t options = [self create_sec_protocol_options];
988
989 sec_protocol_options_append_tls_ciphersuite(options, 1);
990
991 xpc_object_t config = sec_protocol_options_create_config(options);
992 XCTAssertTrue(config != NULL);
993 if (config != NULL) {
994 // Flip a value in the config, and expect the match to fail
995 __block const char *ciphersuites_key = "ciphersuites";
996 xpc_object_t mismatched_config = xpc_dictionary_create(NULL, NULL, 0);
997 xpc_dictionary_apply(config, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
998 if (strncmp(key, ciphersuites_key, strlen(ciphersuites_key)) != 0) {
999 xpc_dictionary_set_value(mismatched_config, key, value);
1000 } else {
1001 xpc_object_t ciphersuites = xpc_array_create(NULL, 0);
1002 xpc_array_set_uint64(ciphersuites, XPC_ARRAY_APPEND, 2);
1003 xpc_dictionary_set_value(mismatched_config, key, ciphersuites);
1004 }
1005 return true;
1006 });
1007 XCTAssertFalse(sec_protocol_options_matches_config(options, mismatched_config));
1008 }
1009 }
1010
1011 - (void)test_protocol_version_map {
1012 #pragma clang diagnostic push
1013 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1014 XCTAssertTrue(tls_protocol_version_TLSv10 == SSLProtocolGetVersionCodepoint(kTLSProtocol1));
1015 XCTAssertTrue(tls_protocol_version_TLSv11 == SSLProtocolGetVersionCodepoint(kTLSProtocol11));
1016 XCTAssertTrue(tls_protocol_version_TLSv12 == SSLProtocolGetVersionCodepoint(kTLSProtocol12));
1017 XCTAssertTrue(tls_protocol_version_TLSv13 == SSLProtocolGetVersionCodepoint(kTLSProtocol13));
1018 XCTAssertTrue(tls_protocol_version_DTLSv12 == SSLProtocolGetVersionCodepoint(kDTLSProtocol12));
1019 XCTAssertTrue(tls_protocol_version_DTLSv10 == SSLProtocolGetVersionCodepoint(kDTLSProtocol1));
1020
1021 XCTAssertTrue(kTLSProtocol1 == SSLProtocolFromVersionCodepoint(tls_protocol_version_TLSv10));
1022 XCTAssertTrue(kTLSProtocol11 == SSLProtocolFromVersionCodepoint(tls_protocol_version_TLSv11));
1023 XCTAssertTrue(kTLSProtocol12 == SSLProtocolFromVersionCodepoint(tls_protocol_version_TLSv12));
1024 XCTAssertTrue(kTLSProtocol13 == SSLProtocolFromVersionCodepoint(tls_protocol_version_TLSv13));
1025 XCTAssertTrue(kDTLSProtocol12 == SSLProtocolFromVersionCodepoint(tls_protocol_version_DTLSv12));
1026 XCTAssertTrue(kDTLSProtocol1 == SSLProtocolFromVersionCodepoint(tls_protocol_version_DTLSv10));
1027 #pragma clang diagnostic pop
1028 }
1029
1030 - (void)test_default_protocol_versions {
1031 XCTAssertTrue(sec_protocol_options_get_default_max_tls_protocol_version() == tls_protocol_version_TLSv13);
1032 XCTAssertTrue(sec_protocol_options_get_default_min_tls_protocol_version() == tls_protocol_version_TLSv10);
1033 XCTAssertTrue(sec_protocol_options_get_default_max_dtls_protocol_version() == tls_protocol_version_DTLSv12);
1034 XCTAssertTrue(sec_protocol_options_get_default_min_dtls_protocol_version() == tls_protocol_version_DTLSv10);
1035 }
1036
1037 - (void)test_sec_protocol_options_set_psk_hint {
1038 __block dispatch_data_t hint = [self create_random_dispatch_data];
1039 sec_protocol_options_t options = [self create_sec_protocol_options];
1040
1041 (void)sec_protocol_options_access_handle(options, ^bool(void * _Nonnull handle) {
1042 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1043 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1044
1045 XCTAssertNil(content->psk_identity_hint, @"PSK identity initialized incorrectly");
1046 });
1047
1048 sec_protocol_options_set_tls_pre_shared_key_identity_hint(options, hint);
1049
1050 (void)sec_protocol_options_access_handle(options, ^bool(void * _Nonnull handle) {
1051 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1052 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1053
1054 XCTAssertTrue(sec_protocol_helper_dispatch_data_equal(content->psk_identity_hint, hint), @"PSK identity mistmatch");
1055 });
1056 }
1057
1058 - (void)test_sec_protocol_options_set_psk_selection_block {
1059 void (^selection_block)(sec_protocol_metadata_t, dispatch_data_t, sec_protocol_pre_shared_key_selection_complete_t) = ^(__unused sec_protocol_metadata_t metadata, __unused dispatch_data_t psk_identity_hint, __unused sec_protocol_pre_shared_key_selection_complete_t complete) {
1060 // pass
1061 };
1062 dispatch_queue_t selection_queue = dispatch_queue_create("test_sec_protocol_options_set_psk_selection_block_queue", DISPATCH_QUEUE_SERIAL);
1063
1064 sec_protocol_options_t options = [self create_sec_protocol_options];
1065 sec_protocol_options_set_pre_shared_key_selection_block(options, selection_block, selection_queue);
1066 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1067 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1068 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1069 XCTAssertTrue(content->psk_selection_block == selection_block);
1070 XCTAssertTrue(content->psk_selection_queue != nil);
1071 return false;
1072 });
1073 }
1074
1075 - (dispatch_data_t)create_random_dispatch_data {
1076 uint8_t random[32];
1077 (void)SecRandomCopyBytes(NULL, sizeof(random), random);
1078 return dispatch_data_create(random, sizeof(random), NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
1079 }
1080
1081 - (void)test_sec_protocol_metadata_access_psks {
1082 __block dispatch_data_t psk_data = [self create_random_dispatch_data];
1083 __block dispatch_data_t psk_identity_data = [self create_random_dispatch_data];
1084
1085 sec_protocol_metadata_t metadata = [self create_sec_protocol_metadata];
1086 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1087 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1088 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1089
1090 content->pre_shared_keys = xpc_array_create(NULL, 0);
1091
1092 xpc_object_t xpc_psk_data = xpc_data_create_with_dispatch_data(psk_data);
1093 xpc_object_t xpc_psk_identity_data = xpc_data_create_with_dispatch_data(psk_identity_data);
1094
1095 xpc_object_t tuple = xpc_array_create(NULL, 0);
1096 xpc_array_set_value(tuple, XPC_ARRAY_APPEND, xpc_psk_data);
1097 xpc_array_set_value(tuple, XPC_ARRAY_APPEND, xpc_psk_identity_data);
1098
1099 xpc_array_set_value(content->pre_shared_keys, XPC_ARRAY_APPEND, tuple);
1100 return true;
1101 });
1102
1103 BOOL accessed = sec_protocol_metadata_access_pre_shared_keys(metadata, ^(dispatch_data_t psk, dispatch_data_t identity) {
1104 XCTAssertTrue(sec_protocol_helper_dispatch_data_equal(psk, psk_data), @"Expected PSK data match");
1105 XCTAssertTrue(sec_protocol_helper_dispatch_data_equal(identity, psk_identity_data), @"Expected PSK identity data match");
1106 });
1107 XCTAssertTrue(accessed, @"Expected sec_protocol_metadata_access_pre_shared_keys to traverse PSK list");
1108 }
1109
1110 @end