]> git.saurik.com Git - apple/security.git/blob - protocol/SecProtocol.c
Security-59306.61.1.tar.gz
[apple/security.git] / protocol / SecProtocol.c
1 //
2 // SecProtocol.c
3 // Security
4 //
5
6 #include <Security/SecProtocolOptions.h>
7 #include <Security/SecProtocolMetadata.h>
8 #include <Security/SecProtocolPriv.h>
9 #include <Security/SecProtocolTypesPriv.h>
10 #include "SecProtocolInternal.h"
11
12 #include <Security/SecureTransportPriv.h>
13
14 #include <Security/SecFramework.h>
15
16 #include <xpc/xpc.h>
17 #include <os/log.h>
18 #include <dlfcn.h>
19 #include <sys/param.h>
20
21 #define MAX_SEC_PROTOCOL_OPTIONS_KEY_LEN 128
22
23 // Options keys
24 #define SEC_PROTOCOL_OPTIONS_KEY_min_version "min_version"
25 #define SEC_PROTOCOL_OPTIONS_KEY_max_version "max_version"
26 #define SEC_PROTOCOL_OPTIONS_KEY_minimum_rsa_key_size "minimum_rsa_key_size"
27 #define SEC_PROTOCOL_OPTIONS_KEY_minimum_ecdsa_key_size "minimum_ecdsa_key_size"
28 #define SEC_PROTOCOL_OPTIONS_KEY_minimum_signature_algorithm "minimum_signature_algorithm"
29 #define SEC_PROTOCOL_OPTIONS_KEY_ats_required "ats_required"
30 #define SEC_PROTOCOL_OPTIONS_KEY_ats_minimum_tls_version_allowed "ats_minimum_tls_version_allowed"
31 #define SEC_PROTOCOL_OPTIONS_KEY_ats_non_pfs_ciphersuite_allowed "ats_non_pfs_ciphersuite_allowed"
32 #define SEC_PROTOCOL_OPTIONS_KEY_trusted_peer_certificate "trusted_peer_certificate"
33 #define SEC_PROTOCOL_OPTIONS_KEY_disable_sni "disable_sni"
34 #define SEC_PROTOCOL_OPTIONS_KEY_enable_fallback_attempt "enable_fallback_attempt"
35 #define SEC_PROTOCOL_OPTIONS_KEY_enable_false_start "enable_false_start"
36 #define SEC_PROTOCOL_OPTIONS_KEY_enable_tickets "enable_tickets"
37 #define SEC_PROTOCOL_OPTIONS_KEY_enable_sct "enable_sct"
38 #define SEC_PROTOCOL_OPTIONS_KEY_enable_ocsp "enable_ocsp"
39 #define SEC_PROTOCOL_OPTIONS_KEY_enforce_ev "enforce_ev"
40 #define SEC_PROTOCOL_OPTIONS_KEY_enable_resumption "enable_resumption"
41 #define SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation "enable_renegotiation"
42 #define SEC_PROTOCOL_OPTIONS_KEY_enable_early_data "enable_early_data"
43 #define SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required "peer_authentication_required"
44 #define SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled "certificate_compression_enabled"
45 #define SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled "tls_SIKE503_exchange_enabled"
46 #define SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled "tls_HRSS_exchange_enabled"
47 #define SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled "eddsa_enabled"
48 #define SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled "tls_delegated_credentials_enabled"
49 #define SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled "tls_grease_enabled"
50 #define SEC_PROTOCOL_OPTIONS_KEY_tls_ticket_request_count "tls_ticket_request_count"
51 #define SEC_PROTOCOL_OPTIONS_KEY_ciphersuites "ciphersuites"
52
53 // Metadata keys
54 #define SEC_PROTOCOL_METADATA_KEY_PROCESS_IDENTIFIER "process"
55 #define SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE "cipher_name"
56 #define SEC_PROTOCOL_METADATA_KEY_FALLBACK_ENABLED "fallback"
57 #define SEC_PROTOCOL_METADATA_KEY_DH_GROUP_SIZE "dhe_size"
58 #define SEC_PROTOCOL_METADATA_KEY_NEGOTIATED_CURVE "neg_curve"
59 #define SEC_PROTOCOL_METADATA_KEY_PEER_CERTIFICATE_REQUEST_TYPE "cert_request_type"
60 #define SEC_PROTOCOL_METADATA_KEY_LOCAL_PRIVATE_KEY_TYPE "private_key_type"
61 #define SEC_PROTOCOL_METADATA_KEY_PEER_PUBLIC_KEY_TYPE "peer_public_key_type"
62 #define SEC_PROTOCOL_METADATA_KEY_NEGOTIATED_PROTOCOL "negotiated_protocol"
63 #define SEC_PROTOCOL_METADATA_KEY_ALPN_USED "alpn_used"
64 #define SEC_PROTOCOL_METADATA_KEY_NPN_USED "npn_used"
65 #define SEC_PROTOCOL_METADATA_KEY_PROTOCOL_VERSION "version"
66 #define SEC_PROTOCOL_METADATA_KEY_FALSE_START_ENABLED "false_start_enabled"
67 #define SEC_PROTOCOL_METADATA_KEY_FALSE_START_USED "false_start_used"
68 #define SEC_PROTOCOL_METADATA_KEY_TICKET_OFFERED "ticket_offered"
69 #define SEC_PROTOCOL_METADATA_KEY_TICKET_RECEIVED "ticket_received"
70 #define SEC_PROTOCOL_METADATA_KEY_SESSION_RESUMED "session_resumed"
71 #define SEC_PROTOCOL_METADATA_KEY_SESSION_RENEWED "session_renewed"
72 #define SEC_PROTOCOL_METADATA_KEY_RESUMPTION_ATTEMPTED "resumption_attempted"
73 #define SEC_PROTOCOL_METADATA_KEY_TICKET_LIFETIME "ticket_lifetime"
74 #define SEC_PROTOCOL_METADATA_KEY_MAX_EARLY_DATA_SUPPORTED "max_early_data_supported"
75 #define SEC_PROTOCOL_METADATA_KEY_OCSP_ENABLED "ocsp_enabled"
76 #define SEC_PROTOCOL_METADATA_KEY_OCSP_RECEIVED "ocsp_received"
77 #define SEC_PROTOCOL_METADATA_KEY_SCT_ENABLED "sct_enabled"
78 #define SEC_PROTOCOL_METADATA_KEY_SCT_RECEIVED "sct_received"
79 #define SEC_PROTOCOL_METADATA_KEY_RSA_SIGNATURE_REQUESTED "client_rsa_requested"
80 #define SEC_PROTOCOL_METADATA_KEY_ECDSA_SIGNATURE_REQUESTED "client_ecdsa_requested"
81 #define SEC_PROTOCOL_METADATA_KEY_FAILURE_ALERT_TYPE "alert_type"
82 #define SEC_PROTOCOL_METADATA_KEY_FAILURE_ALERT_CODE "alert_code"
83 #define SEC_PROTOCOL_METADATA_KEY_FAILURE_HANDSHAKE_STATE "handshake_state"
84 #define SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR "stack_error"
85 #define SEC_PROTOCOL_METADATA_KEY_DEFAULT_EMPTY_STRING "none"
86
87 #define CFReleaseSafe(value) \
88 if (value != NULL) { \
89 CFRelease(value); \
90 }
91
92 bool
93 sec_protocol_options_access_handle(sec_protocol_options_t options,
94 sec_access_block_t access_block)
95 {
96 static void *libnetworkImage = NULL;
97 static dispatch_once_t onceToken;
98 static bool (*_nw_protocol_options_access_handle)(void *, sec_access_block_t) = NULL;
99
100 dispatch_once(&onceToken, ^{
101 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
102 if (NULL != libnetworkImage) {
103 _nw_protocol_options_access_handle = (__typeof(_nw_protocol_options_access_handle))dlsym(libnetworkImage,
104 "nw_protocol_options_access_handle");
105 if (NULL == _nw_protocol_options_access_handle) {
106 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork nw_protocol_options_access_handle");
107 }
108 } else {
109 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
110 }
111 });
112
113 if (_nw_protocol_options_access_handle == NULL) {
114 return false;
115 }
116
117 return _nw_protocol_options_access_handle(options, access_block);
118 }
119
120 bool
121 sec_protocol_metadata_access_handle(sec_protocol_metadata_t options,
122 sec_access_block_t access_block)
123 {
124 static void *libnetworkImage = NULL;
125 static dispatch_once_t onceToken;
126 static bool (*_nw_protocol_metadata_access_handle)(void *, sec_access_block_t) = NULL;
127
128 dispatch_once(&onceToken, ^{
129 libnetworkImage = dlopen("/usr/lib/libnetwork.dylib", RTLD_LAZY | RTLD_LOCAL);
130 if (NULL != libnetworkImage) {
131 _nw_protocol_metadata_access_handle = (__typeof(_nw_protocol_metadata_access_handle))dlsym(libnetworkImage,
132 "nw_protocol_metadata_access_handle");
133 if (NULL == _nw_protocol_metadata_access_handle) {
134 os_log_error(OS_LOG_DEFAULT, "dlsym libnetwork _nw_protocol_metadata_access_handle");
135 }
136 } else {
137 os_log_error(OS_LOG_DEFAULT, "dlopen libnetwork");
138 }
139 });
140
141 if (_nw_protocol_metadata_access_handle == NULL) {
142 return false;
143 }
144
145 return _nw_protocol_metadata_access_handle(options, access_block);
146 }
147
148 #define SEC_PROTOCOL_OPTIONS_VALIDATE(o,r) \
149 if (o == NULL) { \
150 return r; \
151 }
152
153 #define SEC_PROTOCOL_METADATA_VALIDATE(m,r) \
154 if (((void *)m == NULL) || ((size_t)m == 0)) { \
155 return r; \
156 }
157
158 bool
159 sec_protocol_options_contents_are_equal(sec_protocol_options_content_t contentA, sec_protocol_options_content_t contentB)
160 {
161 if (contentA == contentB) {
162 return true;
163 }
164 if (contentA == NULL || contentB == NULL) {
165 return false;
166 }
167
168 sec_protocol_options_content_t optionsA = (sec_protocol_options_content_t)contentA;
169 sec_protocol_options_content_t optionsB = (sec_protocol_options_content_t)contentB;
170
171 // Check boolean and primitive field types first
172 #define CHECK_FIELD(field) \
173 if (optionsA->field != optionsB->field) { \
174 return false; \
175 }
176
177 CHECK_FIELD(min_version);
178 CHECK_FIELD(max_version);
179 CHECK_FIELD(minimum_rsa_key_size);
180 CHECK_FIELD(minimum_ecdsa_key_size);
181 CHECK_FIELD(minimum_signature_algorithm);
182 CHECK_FIELD(tls_ticket_request_count);
183 CHECK_FIELD(ats_required);
184 CHECK_FIELD(ats_minimum_tls_version_allowed);
185 CHECK_FIELD(ats_non_pfs_ciphersuite_allowed);
186 CHECK_FIELD(trusted_peer_certificate);
187 CHECK_FIELD(disable_sni);
188 CHECK_FIELD(enable_fallback_attempt);
189 CHECK_FIELD(enable_false_start);
190 CHECK_FIELD(enable_tickets);
191 CHECK_FIELD(enable_sct);
192 CHECK_FIELD(enable_ocsp);
193 CHECK_FIELD(enforce_ev);
194 CHECK_FIELD(enable_resumption);
195 CHECK_FIELD(enable_renegotiation);
196 CHECK_FIELD(enable_early_data);
197 CHECK_FIELD(peer_authentication_required);
198 CHECK_FIELD(certificate_compression_enabled);
199 CHECK_FIELD(tls_SIKE503_exchange_enabled);
200 CHECK_FIELD(tls_HRSS_exchange_enabled);
201 CHECK_FIELD(eddsa_enabled);
202 CHECK_FIELD(tls_delegated_credentials_enabled);
203 CHECK_FIELD(tls_grease_enabled);
204
205 #undef CHECK_FIELD
206
207 // Check callback block and queue pairs next
208 #define CHECK_BLOCK_QUEUE(block, queue) \
209 if (optionsA->block && optionsB->block) { \
210 if (optionsA->block != optionsB->block) { \
211 return false; \
212 } \
213 if (optionsA->queue != optionsB->queue) { \
214 return false; \
215 } \
216 } else if (optionsA->block || optionsB->block) { \
217 return false; \
218 }
219
220 CHECK_BLOCK_QUEUE(key_update_block, key_update_queue);
221 CHECK_BLOCK_QUEUE(psk_selection_block, psk_selection_queue);
222 CHECK_BLOCK_QUEUE(challenge_block, challenge_queue);
223 CHECK_BLOCK_QUEUE(verify_block, verify_queue);
224 CHECK_BLOCK_QUEUE(tls_secret_update_block, tls_secret_update_queue);
225
226 #undef CHECK_BLOCK_QUEUE
227
228 // Deep compare dispatch data fields
229 #define CHECK_DISPATCH_DATA(data) \
230 if (optionsA->data && optionsB->data) { \
231 if (false == sec_protocol_helper_dispatch_data_equal(optionsA->data, optionsB->data)) { \
232 return false; \
233 } \
234 } else if (optionsA->data || optionsB->data) { \
235 return false; \
236 }
237
238 CHECK_DISPATCH_DATA(dh_params);
239 CHECK_DISPATCH_DATA(quic_transport_parameters);
240 CHECK_DISPATCH_DATA(psk_identity_hint);
241
242 #undef CHECK_DISPATCH_DATA
243
244 // Deep compare XPC objects
245 #define CHECK_XPC_OBJECT(xpc) \
246 if (optionsA->xpc && optionsB->xpc) { \
247 if (false == xpc_equal(optionsA->xpc, optionsB->xpc)) { \
248 return false; \
249 } \
250 } else if (optionsA->xpc || optionsB->xpc) { \
251 return false; \
252 }
253
254 CHECK_XPC_OBJECT(application_protocols);
255 CHECK_XPC_OBJECT(ciphersuites);
256 CHECK_XPC_OBJECT(key_exchange_groups);
257 CHECK_XPC_OBJECT(pre_shared_keys);
258
259 #undef CHECK_XPC_OBJECT
260
261 // Deep compare all other fields
262 if (optionsA->server_name && optionsB->server_name) {
263 if (0 != strcmp(optionsA->server_name, optionsB->server_name)) {
264 return false;
265 }
266 } else if (optionsA->server_name || optionsB->server_name) {
267 return false;
268 }
269
270 if (optionsA->identity && optionsB->identity) {
271 SecIdentityRef identityA = sec_identity_copy_ref((sec_identity_t)optionsA->identity);
272 SecIdentityRef identityB = sec_identity_copy_ref((sec_identity_t)optionsB->identity);
273
274 if (false == CFEqual(identityA, identityB)) {
275 return false;
276 }
277
278 CFRelease(identityA);
279 CFRelease(identityB);
280 } else if (optionsA->identity || optionsB->identity) {
281 return false;
282 }
283
284 if (optionsA->output_handler_access_block && optionsB->output_handler_access_block) {
285 if (optionsA->output_handler_access_block != optionsB->output_handler_access_block) {
286 return false;
287 }
288 } else if (optionsA->output_handler_access_block || optionsB->output_handler_access_block) {
289 return false;
290 }
291
292 return true;
293 }
294
295 bool
296 sec_protocol_options_are_equal(sec_protocol_options_t handleA, sec_protocol_options_t handleB)
297 {
298 if (handleA == handleB) {
299 return true;
300 }
301 if (handleA == NULL || handleB == NULL) {
302 return false;
303 }
304
305 return sec_protocol_options_access_handle(handleA, ^bool(void *innerA) {
306 sec_protocol_options_content_t optionsA = (sec_protocol_options_content_t)innerA;
307 return sec_protocol_options_access_handle(handleB, ^bool(void *innerB) {
308 sec_protocol_options_content_t optionsB = (sec_protocol_options_content_t)innerB;
309 return sec_protocol_options_contents_are_equal(optionsA, optionsB);
310 });
311 });
312 }
313
314 void
315 sec_protocol_options_set_local_identity(sec_protocol_options_t options, sec_identity_t identity)
316 {
317 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
318
319 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
320 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
321 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
322
323 if (content->identity != NULL) {
324 sec_release(content->identity);
325 }
326 content->identity = sec_retain(identity);
327 return true;
328 });
329 }
330
331 void
332 sec_protocol_options_append_tls_ciphersuite(sec_protocol_options_t options, tls_ciphersuite_t ciphersuite)
333 {
334 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
335
336 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
337 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
338 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
339
340 if (content->ciphersuites == NULL) {
341 content->ciphersuites = xpc_array_create(NULL, 0);
342 }
343 xpc_array_set_uint64(content->ciphersuites, XPC_ARRAY_APPEND, (uint64_t)ciphersuite);
344 return true;
345 });
346 }
347
348 void
349 sec_protocol_options_add_tls_ciphersuite(sec_protocol_options_t options, SSLCipherSuite ciphersuite)
350 {
351 sec_protocol_options_append_tls_ciphersuite(options, (tls_ciphersuite_t)ciphersuite);
352 }
353
354 void
355 sec_protocol_options_append_tls_ciphersuite_group(sec_protocol_options_t options, tls_ciphersuite_group_t group)
356 {
357 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
358
359 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
360 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
361 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
362
363 // Fetch the list of ciphersuites associated with the ciphersuite group
364 size_t ciphersuite_count = 0;
365 const tls_ciphersuite_t *list = sec_protocol_helper_ciphersuite_group_to_ciphersuite_list(group, &ciphersuite_count);
366 if (list != NULL) {
367 if (content->ciphersuites == NULL) {
368 content->ciphersuites = xpc_array_create(NULL, 0);
369 }
370
371 for (size_t i = 0; i < ciphersuite_count; i++) {
372 tls_ciphersuite_t ciphersuite = list[i];
373 xpc_array_set_uint64(content->ciphersuites, XPC_ARRAY_APPEND, (uint64_t)ciphersuite);
374 }
375 }
376
377 return true;
378 });
379 }
380
381 void
382 sec_protocol_options_add_tls_ciphersuite_group(sec_protocol_options_t options, SSLCiphersuiteGroup group)
383 {
384 switch (group) {
385 case kSSLCiphersuiteGroupDefault:
386 return sec_protocol_options_append_tls_ciphersuite_group(options, tls_ciphersuite_group_default);
387 case kSSLCiphersuiteGroupCompatibility:
388 return sec_protocol_options_append_tls_ciphersuite_group(options, tls_ciphersuite_group_compatibility);
389 case kSSLCiphersuiteGroupLegacy:
390 return sec_protocol_options_append_tls_ciphersuite_group(options, tls_ciphersuite_group_legacy);
391 case kSSLCiphersuiteGroupATS:
392 return sec_protocol_options_append_tls_ciphersuite_group(options, tls_ciphersuite_group_ats);
393 case kSSLCiphersuiteGroupATSCompatibility:
394 return sec_protocol_options_append_tls_ciphersuite_group(options, tls_ciphersuite_group_ats_compatibility);
395 }
396 }
397
398 void
399 sec_protocol_options_clear_tls_ciphersuites(sec_protocol_options_t options)
400 {
401 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
402
403 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
404 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
405 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
406
407 if (content->ciphersuites != NULL) {
408 xpc_release(content->ciphersuites);
409 content->ciphersuites = NULL;
410 }
411 return true;
412 });
413 }
414
415 void
416 sec_protocol_options_set_tls_min_version(sec_protocol_options_t options, SSLProtocol version)
417 {
418 tls_protocol_version_t protocol_version = (tls_protocol_version_t)SSLProtocolGetVersionCodepoint(version);
419 if (protocol_version != 0) {
420 sec_protocol_options_set_min_tls_protocol_version(options, protocol_version);
421 }
422 }
423
424 void
425 sec_protocol_options_set_min_tls_protocol_version(sec_protocol_options_t options, tls_protocol_version_t version)
426 {
427 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
428
429 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
430 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
431 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
432
433 SSLProtocol converted_protocol = SSLProtocolFromVersionCodepoint(version);
434 content->min_version = converted_protocol;
435 return true;
436 });
437 }
438
439 tls_protocol_version_t
440 sec_protocol_options_get_default_min_tls_protocol_version(void)
441 {
442 return tls_protocol_version_TLSv10;
443 }
444
445 tls_protocol_version_t
446 sec_protocol_options_get_default_min_dtls_protocol_version(void)
447 {
448 return tls_protocol_version_DTLSv10;
449 }
450
451 void
452 sec_protocol_options_set_tls_max_version(sec_protocol_options_t options, SSLProtocol version)
453 {
454 tls_protocol_version_t protocol_version = (tls_protocol_version_t)SSLProtocolGetVersionCodepoint(version);
455 if (protocol_version != 0) {
456 sec_protocol_options_set_max_tls_protocol_version(options, protocol_version);
457 }
458 }
459
460 void
461 sec_protocol_options_set_max_tls_protocol_version(sec_protocol_options_t options, tls_protocol_version_t version)
462 {
463 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
464
465 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
466 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
467 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
468
469 SSLProtocol converted_protocol = SSLProtocolFromVersionCodepoint(version);
470 content->max_version = converted_protocol;
471 return true;
472 });
473 }
474
475 tls_protocol_version_t
476 sec_protocol_options_get_default_max_tls_protocol_version(void)
477 {
478 return tls_protocol_version_TLSv13;
479 }
480
481 tls_protocol_version_t
482 sec_protocol_options_get_default_max_dtls_protocol_version(void)
483 {
484 return tls_protocol_version_DTLSv12;
485 }
486
487 void
488 sec_protocol_options_add_tls_application_protocol(sec_protocol_options_t options, const char *application_protocol)
489 {
490 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
491 SEC_PROTOCOL_OPTIONS_VALIDATE(application_protocol,);
492
493 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
494 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
495 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
496
497 if (content->application_protocols == NULL) {
498 content->application_protocols = xpc_array_create(NULL, 0);
499 }
500 xpc_array_set_string(content->application_protocols, XPC_ARRAY_APPEND, application_protocol);
501 return true;
502 });
503 }
504
505 void
506 sec_protocol_options_set_tls_server_name(sec_protocol_options_t options, const char *server_name)
507 {
508 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
509 SEC_PROTOCOL_OPTIONS_VALIDATE(server_name,);
510
511 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
512 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
513 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
514
515 CFStringRef serverName = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingUTF8);
516 if (serverName == NULL) {
517 return false;
518 }
519 if (!SecFrameworkIsDNSName(serverName)) {
520 CFRelease(serverName);
521 return false;
522 }
523 CFRelease(serverName);
524
525 free(content->server_name);
526 content->server_name = strdup(server_name);
527 return true;
528 });
529 }
530
531 void
532 sec_protocol_options_set_tls_diffie_hellman_parameters(sec_protocol_options_t options, dispatch_data_t params)
533 {
534 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
535 SEC_PROTOCOL_OPTIONS_VALIDATE(params,);
536
537 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
538 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
539 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
540
541 if (content->dh_params) {
542 dispatch_release(content->dh_params);
543 }
544 content->dh_params = params;
545 dispatch_retain(params);
546 return true;
547 });
548 }
549
550 void
551 sec_protocol_options_add_pre_shared_key(sec_protocol_options_t options, dispatch_data_t psk, dispatch_data_t psk_identity)
552 {
553 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
554 SEC_PROTOCOL_OPTIONS_VALIDATE(psk,);
555 SEC_PROTOCOL_OPTIONS_VALIDATE(psk_identity,);
556
557 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
558 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
559 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
560
561 if (content->pre_shared_keys == NULL) {
562 content->pre_shared_keys = xpc_array_create(NULL, 0);
563 }
564
565 xpc_object_t psk_data = xpc_data_create_with_dispatch_data(psk);
566 xpc_object_t psk_identity_data = xpc_data_create_with_dispatch_data(psk_identity);
567
568 xpc_object_t tuple = xpc_array_create(NULL, 0);
569 xpc_array_set_value(tuple, XPC_ARRAY_APPEND, psk_data);
570 xpc_array_set_value(tuple, XPC_ARRAY_APPEND, psk_identity_data);
571 xpc_release(psk_data);
572 xpc_release(psk_identity_data);
573
574 xpc_array_set_value(content->pre_shared_keys, XPC_ARRAY_APPEND, tuple);
575 xpc_release(tuple);
576 return true;
577 });
578 }
579
580 void
581 sec_protocol_options_set_tls_pre_shared_key_identity_hint(sec_protocol_options_t options, dispatch_data_t psk_identity_hint)
582 {
583 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
584 SEC_PROTOCOL_OPTIONS_VALIDATE(psk_identity_hint,);
585
586 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
587 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
588 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
589
590 if (content->psk_identity_hint != NULL) {
591 dispatch_release(content->psk_identity_hint);
592 }
593
594 content->psk_identity_hint = psk_identity_hint;
595 dispatch_retain(psk_identity_hint);
596 return true;
597 });
598 }
599
600 void
601 sec_protocol_options_set_pre_shared_key_selection_block(sec_protocol_options_t options, sec_protocol_pre_shared_key_selection_t psk_selection_block, dispatch_queue_t psk_selection_queue)
602 {
603 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
604 SEC_PROTOCOL_OPTIONS_VALIDATE(psk_selection_block,);
605 SEC_PROTOCOL_OPTIONS_VALIDATE(psk_selection_queue,);
606
607 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
608 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
609 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
610
611 if (content->psk_selection_block != NULL) {
612 Block_release(content->psk_selection_block);
613 }
614 if (content->psk_selection_queue != NULL) {
615 dispatch_release(content->psk_selection_queue);
616 }
617
618 content->psk_selection_block = Block_copy(psk_selection_block);
619 content->psk_selection_queue = psk_selection_queue;
620 dispatch_retain(content->psk_selection_queue);
621 return true;
622 });
623 }
624
625 void
626 sec_protocol_options_set_tls_is_fallback_attempt(sec_protocol_options_t options, bool fallback_attempt)
627 {
628 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
629
630 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
631 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
632 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
633
634 content->enable_fallback_attempt = fallback_attempt;
635 content->enable_fallback_attempt_override = true;
636 return true;
637 });
638 }
639
640 void
641 sec_protocol_options_set_tls_tickets_enabled(sec_protocol_options_t options, bool tickets_enabled)
642 {
643 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
644
645 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
646 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
647 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
648
649 content->enable_tickets = tickets_enabled;
650 content->enable_tickets_override = true;
651 return true;
652 });
653 }
654
655 void
656 sec_protocol_options_set_tls_resumption_enabled(sec_protocol_options_t options, bool resumption_enabled)
657 {
658 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
659
660 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
661 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
662 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
663
664 content->enable_resumption = resumption_enabled;
665 content->enable_resumption_override = true;
666 return true;
667 });
668 }
669
670 void
671 sec_protocol_options_set_tls_false_start_enabled(sec_protocol_options_t options, bool false_start_enabled)
672 {
673 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
674
675 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
676 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
677 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
678
679 content->enable_false_start = false_start_enabled;
680 content->enable_false_start_override = true;
681 return true;
682 });
683 }
684
685 void
686 sec_protocol_options_set_tls_early_data_enabled(sec_protocol_options_t options, bool early_data_enabled)
687 {
688 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
689
690 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
691 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
692 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
693
694 content->enable_early_data = early_data_enabled;
695 content->enable_early_data_override = true;
696 return true;
697 });
698 }
699
700 void
701 sec_protocol_options_set_tls_sni_disabled(sec_protocol_options_t options, bool sni_disabled)
702 {
703 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
704
705 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
706 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
707 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
708
709 content->disable_sni = sni_disabled;
710 content->disable_sni_override = true;
711 return true;
712 });
713 }
714
715 void
716 sec_protocol_options_set_enforce_ev(sec_protocol_options_t options, bool enforce_ev)
717 {
718 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
719
720 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
721 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
722 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
723
724 content->enforce_ev = enforce_ev;
725 content->enforce_ev_override = true;
726 return true;
727 });
728 }
729
730 void
731 sec_protocol_options_set_tls_ocsp_enabled(sec_protocol_options_t options, bool ocsp_enabled)
732 {
733 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
734
735 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
736 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
737 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
738
739 content->enable_ocsp = ocsp_enabled;
740 content->enable_ocsp_override = true;
741 return true;
742 });
743 }
744
745 void
746 sec_protocol_options_set_tls_sct_enabled(sec_protocol_options_t options, bool sct_enabled)
747 {
748 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
749
750 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
751 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
752 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
753
754 content->enable_sct = sct_enabled;
755 content->enable_sct_override = true;
756 return true;
757 });
758 }
759
760 void
761 sec_protocol_options_set_tls_renegotiation_enabled(sec_protocol_options_t options, bool renegotiation_enabled)
762 {
763 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
764
765 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
766 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
767 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
768
769 content->enable_renegotiation = renegotiation_enabled;
770 content->enable_renegotiation_override = true;
771 return true;
772 });
773 }
774
775 void
776 sec_protocol_options_set_peer_authentication_required(sec_protocol_options_t options, bool peer_authentication_required)
777 {
778 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
779
780 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
781 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
782 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
783
784 content->peer_authentication_required = peer_authentication_required;
785 content->peer_authentication_override = true;
786 return true;
787 });
788 }
789
790 void
791 sec_protocol_options_set_key_update_block(sec_protocol_options_t options, sec_protocol_key_update_t update_block, dispatch_queue_t update_queue)
792 {
793 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
794 SEC_PROTOCOL_OPTIONS_VALIDATE(update_queue,);
795
796 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
797 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
798 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
799
800 if (content->key_update_block != NULL) {
801 Block_release(content->key_update_block);
802 }
803 if (content->key_update_queue != NULL) {
804 dispatch_release(content->key_update_queue);
805 }
806
807 content->key_update_block = Block_copy(update_block);
808 content->key_update_queue = Block_copy(update_queue);
809 dispatch_retain(content->key_update_queue);
810 return true;
811 });
812 }
813
814 void
815 sec_protocol_options_set_challenge_block(sec_protocol_options_t options, sec_protocol_challenge_t challenge_block, dispatch_queue_t challenge_queue)
816 {
817 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
818 SEC_PROTOCOL_OPTIONS_VALIDATE(challenge_queue,);
819
820 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
821 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
822 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
823
824 if (content->challenge_block != NULL) {
825 Block_release(content->challenge_block);
826 }
827 if (content->challenge_queue != NULL) {
828 dispatch_release(content->challenge_queue);
829 }
830
831 content->challenge_block = Block_copy(challenge_block);
832 content->challenge_queue = challenge_queue;
833 dispatch_retain(content->challenge_queue);
834 return true;
835 });
836 }
837
838 void
839 sec_protocol_options_set_verify_block(sec_protocol_options_t options, sec_protocol_verify_t verify_block, dispatch_queue_t verify_queue)
840 {
841 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
842 SEC_PROTOCOL_OPTIONS_VALIDATE(verify_queue,);
843
844 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
845 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
846 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
847
848 if (content->verify_block != NULL) {
849 Block_release(content->verify_block);
850 }
851 if (content->verify_queue != NULL) {
852 dispatch_release(content->verify_queue);
853 }
854
855 content->verify_block = Block_copy(verify_block);
856 content->verify_queue = verify_queue;
857 dispatch_retain(content->verify_queue);
858 return true;
859 });
860 }
861
862 void
863 sec_protocol_options_set_session_update_block(sec_protocol_options_t options, sec_protocol_session_update_t update_block, dispatch_queue_t update_queue)
864 {
865 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
866 SEC_PROTOCOL_OPTIONS_VALIDATE(update_block,);
867 SEC_PROTOCOL_OPTIONS_VALIDATE(update_queue,);
868
869 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
870 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
871 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
872
873 if (content->session_update_block != NULL) {
874 Block_release(content->session_update_block);
875 }
876 if (content->session_update_queue != NULL) {
877 dispatch_release(content->session_update_queue);
878 }
879
880 content->session_update_block = Block_copy(update_block);
881 content->session_update_queue = update_queue;
882 dispatch_retain(content->session_update_queue);
883 return true;
884 });
885 }
886
887 void
888 sec_protocol_options_set_tls_encryption_secret_update_block(sec_protocol_options_t options, sec_protocol_tls_encryption_secret_update_t update_block, dispatch_queue_t update_queue)
889 {
890 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
891 SEC_PROTOCOL_OPTIONS_VALIDATE(update_block,);
892 SEC_PROTOCOL_OPTIONS_VALIDATE(update_queue,);
893
894 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
895 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
896 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
897
898 if (content->tls_secret_update_block != NULL) {
899 Block_release(content->tls_secret_update_block);
900 }
901 if (content->tls_secret_update_queue != NULL) {
902 dispatch_release(content->tls_secret_update_queue);
903 }
904
905 content->tls_secret_update_block = Block_copy(update_block);
906 content->tls_secret_update_queue = update_queue;
907 dispatch_retain(content->tls_secret_update_queue);
908 return true;
909 });
910 }
911
912 void
913 sec_protocol_options_set_session_state(sec_protocol_options_t options, dispatch_data_t session_state)
914 {
915 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
916 SEC_PROTOCOL_OPTIONS_VALIDATE(session_state,);
917
918 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
919 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
920 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
921
922 if (content->session_state != NULL) {
923 dispatch_release(content->session_state);
924 }
925
926 content->session_state = session_state;
927 dispatch_retain(session_state);
928 return true;
929 });
930 }
931
932 void
933 sec_protocol_options_set_quic_transport_parameters(sec_protocol_options_t options, dispatch_data_t transport_parameters)
934 {
935 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
936 SEC_PROTOCOL_OPTIONS_VALIDATE(transport_parameters,);
937
938 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
939 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
940 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
941
942 if (content->quic_transport_parameters != NULL) {
943 dispatch_release(content->quic_transport_parameters);
944 }
945
946 content->quic_transport_parameters = transport_parameters;
947 dispatch_retain(transport_parameters);
948 return true;
949 });
950 }
951
952 void
953 sec_protocol_options_set_ats_required(sec_protocol_options_t options, bool required)
954 {
955 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
956
957 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
958 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
959 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
960
961 content->ats_required = required;
962 return true;
963 });
964 }
965
966 void
967 sec_protocol_options_set_minimum_rsa_key_size(sec_protocol_options_t options, size_t minimum_key_size)
968 {
969 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
970
971 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
972 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
973 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
974
975 content->minimum_rsa_key_size = minimum_key_size;
976 return true;
977 });
978 }
979
980 void
981 sec_protocol_options_set_minimum_ecdsa_key_size(sec_protocol_options_t options, size_t minimum_key_size)
982 {
983 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
984
985 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
986 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
987 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
988
989 content->minimum_ecdsa_key_size = minimum_key_size;
990 return true;
991 });
992 }
993
994 void
995 sec_protocol_options_set_minimum_signature_algorithm(sec_protocol_options_t options, SecSignatureHashAlgorithm algorithm)
996 {
997 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
998
999 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1000 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1001 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1002
1003 content->minimum_signature_algorithm = algorithm;
1004 return true;
1005 });
1006 }
1007
1008 void
1009 sec_protocol_options_set_trusted_peer_certificate(sec_protocol_options_t options, bool trusted_peer_certificate)
1010 {
1011 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1012
1013 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1014 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1015 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1016
1017 content->trusted_peer_certificate = trusted_peer_certificate;
1018 content->trusted_peer_certificate_override = true;
1019 return true;
1020 });
1021 }
1022
1023 void
1024 sec_protocol_options_set_private_key_blocks(sec_protocol_options_t options,
1025 sec_protocol_private_key_sign_t sign_block,
1026 sec_protocol_private_key_decrypt_t decrypt_block,
1027 dispatch_queue_t operation_queue)
1028 {
1029 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1030 SEC_PROTOCOL_OPTIONS_VALIDATE(sign_block,);
1031 SEC_PROTOCOL_OPTIONS_VALIDATE(decrypt_block,);
1032 SEC_PROTOCOL_OPTIONS_VALIDATE(operation_queue,);
1033
1034 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1035 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1036 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1037
1038 if (content->private_key_sign_block != NULL) {
1039 Block_release(content->private_key_sign_block);
1040 }
1041 if (content->private_key_decrypt_block != NULL) {
1042 Block_release(content->private_key_decrypt_block);
1043 }
1044 if (content->private_key_queue != NULL) {
1045 dispatch_release(content->private_key_queue);
1046 }
1047
1048 content->private_key_sign_block = Block_copy(sign_block);
1049 content->private_key_decrypt_block = Block_copy(decrypt_block);
1050 content->private_key_queue = operation_queue;
1051 dispatch_retain(content->private_key_queue);
1052
1053 return true;
1054 });
1055 }
1056
1057 void
1058 sec_protocol_options_set_local_certificates(sec_protocol_options_t options, sec_array_t certificates)
1059 {
1060 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1061 SEC_PROTOCOL_OPTIONS_VALIDATE(certificates,);
1062
1063 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1064 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1065 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1066
1067 if (content->certificates != NULL) {
1068 sec_release(content->certificates);
1069 }
1070
1071 content->certificates = certificates;
1072 sec_retain(content->certificates);
1073 return true;
1074 });
1075 }
1076
1077 void
1078 sec_protocol_options_set_tls_certificate_compression_enabled(sec_protocol_options_t options, bool certificate_compression_enabled)
1079 {
1080 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1081
1082 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1083 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1084 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1085
1086 content->certificate_compression_enabled = certificate_compression_enabled;
1087 return true;
1088 });
1089 }
1090
1091 void
1092 sec_protocol_options_set_output_handler_access_block(sec_protocol_options_t options,
1093 sec_protocol_output_handler_access_block_t access_block)
1094 {
1095 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1096 SEC_PROTOCOL_OPTIONS_VALIDATE(access_block,);
1097
1098 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1099 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1100 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1101
1102 content->output_handler_access_block = Block_copy(access_block);
1103 return true;
1104 });
1105 }
1106
1107 void
1108 sec_protocol_options_tls_handshake_message_callback(sec_protocol_options_t options, sec_protocol_tls_handshake_message_handler_t handler, dispatch_queue_t queue)
1109 {
1110 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1111 SEC_PROTOCOL_OPTIONS_VALIDATE(handler,);
1112 SEC_PROTOCOL_OPTIONS_VALIDATE(queue,);
1113
1114 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1115 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1116 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1117
1118 if (content->handshake_message_callback != NULL) {
1119 Block_release(content->handshake_message_callback);
1120 }
1121 if (content->handshake_message_callback_queue != NULL) {
1122 dispatch_release(content->handshake_message_callback_queue);
1123 }
1124
1125 content->handshake_message_callback = Block_copy(handler);
1126 content->handshake_message_callback_queue = queue;
1127 dispatch_retain(content->handshake_message_callback_queue);
1128
1129 return true;
1130 });
1131 }
1132
1133 void
1134 sec_protocol_options_set_tls_SIKE503_exchange_enabled(sec_protocol_options_t options, bool tls_SIKE503_exchange_enabled)
1135 {
1136 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1137
1138 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1139 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1140 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1141
1142 content->tls_SIKE503_exchange_enabled = tls_SIKE503_exchange_enabled;
1143 return true;
1144 });
1145 }
1146
1147 void
1148 sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t options, bool tls_HRSS_exchange_enabled)
1149 {
1150 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1151
1152 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1153 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1154 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1155
1156 content->tls_HRSS_exchange_enabled = tls_HRSS_exchange_enabled;
1157 return true;
1158 });
1159 }
1160
1161 void
1162 sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled)
1163 {
1164 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1165
1166 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1167 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1168 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1169
1170 content->eddsa_enabled = eddsa_enabled;
1171 return true;
1172 });
1173 }
1174
1175 void
1176 sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_t options, bool tls_delegated_credentials_enabled)
1177 {
1178 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1179
1180 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1181 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1182 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1183
1184 content->tls_delegated_credentials_enabled = tls_delegated_credentials_enabled;
1185 return true;
1186 });
1187 }
1188
1189 void
1190 sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled)
1191 {
1192 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1193
1194 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1195 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1196 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1197
1198 content->tls_grease_enabled = tls_grease_enabled;
1199 return true;
1200 });
1201 }
1202
1203 void
1204 sec_protocol_options_set_experiment_identifier(sec_protocol_options_t options, const char *experiment_identifier)
1205 {
1206 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1207 SEC_PROTOCOL_OPTIONS_VALIDATE(experiment_identifier,);
1208
1209 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1210 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1211 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1212
1213 if (content->experiment_identifier != NULL) {
1214 free(content->experiment_identifier);
1215 }
1216 if (experiment_identifier != NULL) {
1217 content->experiment_identifier = strdup(experiment_identifier);
1218 }
1219 return true;
1220 });
1221 }
1222
1223 void
1224 sec_protocol_options_set_connection_id(sec_protocol_options_t options, uuid_t _Nonnull connection_id)
1225 {
1226 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1227 SEC_PROTOCOL_OPTIONS_VALIDATE(connection_id,);
1228
1229 sec_protocol_options_access_handle(options, ^bool(void *handle) {
1230 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1231 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1232
1233 memcpy(content->connection_id, connection_id, sizeof(content->connection_id));
1234 return true;
1235 });
1236 }
1237
1238 void
1239 sec_protocol_options_set_tls_ticket_request_count(sec_protocol_options_t options, uint8_t tls_ticket_request_count)
1240 {
1241 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1242
1243 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1244 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1245 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1246
1247 content->tls_ticket_request_count = tls_ticket_request_count;
1248 return true;
1249 });
1250 }
1251
1252 void
1253 sec_protocol_options_set_ats_non_pfs_ciphersuite_allowed(sec_protocol_options_t options, bool ats_non_pfs_ciphersuite_allowed)
1254 {
1255 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1256
1257 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1258 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1259 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1260
1261 content->ats_non_pfs_ciphersuite_allowed = ats_non_pfs_ciphersuite_allowed;
1262 return true;
1263 });
1264 }
1265
1266 void
1267 sec_protocol_options_set_ats_minimum_tls_version_allowed(sec_protocol_options_t options, bool ats_minimum_tls_version_allowed)
1268 {
1269 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1270
1271 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1272 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1273 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1274
1275 content->ats_minimum_tls_version_allowed = ats_minimum_tls_version_allowed;
1276 return true;
1277 });
1278 }
1279
1280 void
1281 sec_protocol_options_append_tls_key_exchange_group(sec_protocol_options_t options, tls_key_exchange_group_t group)
1282 {
1283 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1284
1285 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1286 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1287 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1288
1289 if (content->key_exchange_groups == NULL) {
1290 content->key_exchange_groups = xpc_array_create(NULL, 0);
1291 }
1292 xpc_array_set_uint64(content->key_exchange_groups, XPC_ARRAY_APPEND, (uint64_t)group);
1293 return true;
1294 });
1295 }
1296
1297 void
1298 sec_protocol_options_add_tls_key_exchange_group(sec_protocol_options_t options, SSLKeyExchangeGroup group)
1299 {
1300 return sec_protocol_options_append_tls_key_exchange_group(options, (tls_key_exchange_group_t)group);
1301 }
1302
1303 void
1304 sec_protocol_options_append_tls_key_exchange_group_set(sec_protocol_options_t options, tls_key_exchange_group_set_t set)
1305 {
1306 SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
1307
1308 (void)sec_protocol_options_access_handle(options, ^bool(void *handle) {
1309 sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
1310 SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
1311
1312 if (content->key_exchange_groups == NULL) {
1313 content->key_exchange_groups = xpc_array_create(NULL, 0);
1314 }
1315
1316 // Fetch the list of ciphersuites associated with the ciphersuite group
1317 size_t group_set_count = 0;
1318 const tls_key_exchange_group_t *group_set = sec_protocol_helper_tls_key_exchange_group_set_to_key_exchange_group_list(set, &group_set_count);
1319 if (group_set != NULL) {
1320 for (size_t i = 0; i < group_set_count; i++) {
1321 tls_key_exchange_group_t group = group_set[i];
1322 xpc_array_set_uint64(content->key_exchange_groups, XPC_ARRAY_APPEND, (uint64_t)group);
1323 }
1324 }
1325
1326 return true;
1327 });
1328 }
1329
1330 void
1331 sec_protocol_options_add_tls_key_exchange_group_set(sec_protocol_options_t options, SSLKeyExchangeGroupSet set)
1332 {
1333 switch (set) {
1334 case kSSLKeyExchangeGroupSetDefault:
1335 sec_protocol_options_append_tls_key_exchange_group_set(options, tls_key_exchange_group_set_default);
1336 break;
1337 case kSSLKeyExchangeGroupSetCompatibility:
1338 sec_protocol_options_append_tls_key_exchange_group_set(options, tls_key_exchange_group_set_compatibility);
1339 break;
1340 case kSSLKeyExchangeGroupSetLegacy:
1341 sec_protocol_options_append_tls_key_exchange_group_set(options, tls_key_exchange_group_set_legacy);
1342 break;
1343 }
1344 }
1345
1346 const char *
1347 sec_protocol_metadata_get_negotiated_protocol(sec_protocol_metadata_t metadata)
1348 {
1349 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
1350
1351 __block const char *negotiated_protocol = NULL;
1352 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1353 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1354 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1355 negotiated_protocol = content->negotiated_protocol;
1356 return true;
1357 });
1358
1359 return negotiated_protocol;
1360 }
1361
1362 const char *
1363 sec_protocol_metadata_get_server_name(sec_protocol_metadata_t metadata)
1364 {
1365 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
1366
1367 __block const char *server_name = NULL;
1368 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1369 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1370 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1371 server_name = content->server_name;
1372 return true;
1373 });
1374
1375 return server_name;
1376 }
1377
1378 uint64_t
1379 sec_protocol_metadata_get_handshake_time_ms(sec_protocol_metadata_t metadata)
1380 {
1381 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1382
1383 __block uint64_t time = 0;
1384 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1385 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1386 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1387 time = metadata_content->handshake_time;
1388 return true;
1389 });
1390
1391 return time;
1392 }
1393
1394 uint64_t
1395 sec_protocol_metadata_get_handshake_byte_count(sec_protocol_metadata_t metadata)
1396 {
1397 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1398
1399 __block uint64_t count = 0;
1400 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1401 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1402 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1403 count = metadata_content->total_byte_count;
1404 return true;
1405 });
1406
1407 return count;
1408 }
1409
1410 uint64_t
1411 sec_protocol_metadata_get_handshake_sent_byte_count(sec_protocol_metadata_t metadata)
1412 {
1413 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1414
1415 __block uint64_t count = 0;
1416 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1417 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1418 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1419 count = metadata_content->sent_byte_count;
1420 return true;
1421 });
1422
1423 return count;
1424 }
1425
1426 uint64_t
1427 sec_protocol_metadata_get_handshake_received_byte_count(sec_protocol_metadata_t metadata)
1428 {
1429 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1430
1431 __block uint64_t count = 0;
1432 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1433 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1434 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1435 count = metadata_content->received_byte_count;
1436 return true;
1437 });
1438
1439 return count;
1440 }
1441
1442 size_t
1443 sec_protocol_metadata_get_handshake_read_stall_count(sec_protocol_metadata_t metadata)
1444 {
1445 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1446
1447 __block size_t count = 0;
1448 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1449 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1450 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1451 count = metadata_content->read_stall_count;
1452 return true;
1453 });
1454
1455 return count;
1456 }
1457
1458 size_t
1459 sec_protocol_metadata_get_handshake_write_stall_count(sec_protocol_metadata_t metadata)
1460 {
1461 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1462
1463 __block size_t count = 0;
1464 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1465 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1466 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1467 count = metadata_content->write_stall_count;
1468 return true;
1469 });
1470
1471 return count;
1472 }
1473
1474 size_t
1475 sec_protocol_metadata_get_handshake_async_call_count(sec_protocol_metadata_t metadata)
1476 {
1477 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
1478
1479 __block size_t count = 0;
1480 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
1481 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
1482 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
1483 count = metadata_content->async_call_count;
1484 return true;
1485 });
1486
1487 return count;
1488 }
1489
1490 bool
1491 sec_protocol_metadata_access_peer_certificate_chain(sec_protocol_metadata_t metadata,
1492 void (^handler)(sec_certificate_t certficate))
1493 {
1494 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1495 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
1496
1497 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1498 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1499 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1500 if (content->peer_certificate_chain == NULL) {
1501 return false;
1502 }
1503 sec_array_t array = content->peer_certificate_chain;
1504 sec_array_apply(array, ^bool(__unused size_t index, sec_object_t object) {
1505 handler((sec_certificate_t)object);
1506 return true;
1507 });
1508 return true;
1509 });
1510 }
1511
1512 dispatch_data_t
1513 sec_protocol_metadata_copy_peer_public_key(sec_protocol_metadata_t metadata)
1514 {
1515 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
1516
1517 __block dispatch_data_t peer_public_key = NULL;
1518 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1519 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1520 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1521 peer_public_key = ((dispatch_data_t)content->peer_public_key);
1522 if (peer_public_key) {
1523 dispatch_retain(peer_public_key);
1524 }
1525 return true;
1526 });
1527
1528 return peer_public_key;
1529 }
1530
1531 tls_protocol_version_t
1532 sec_protocol_metadata_get_negotiated_tls_protocol_version(sec_protocol_metadata_t metadata)
1533 {
1534 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0x0000);
1535
1536 __block tls_protocol_version_t protocol_version = 0x0000;
1537 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1538 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1539 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1540 protocol_version = SSLProtocolGetVersionCodepoint(content->negotiated_protocol_version);
1541 return true;
1542 });
1543
1544 return protocol_version;
1545 }
1546
1547 SSLProtocol
1548 sec_protocol_metadata_get_negotiated_protocol_version(sec_protocol_metadata_t metadata)
1549 {
1550 SEC_PROTOCOL_METADATA_VALIDATE(metadata, kSSLProtocolUnknown);
1551
1552 __block SSLProtocol protocol_version = kSSLProtocolUnknown;
1553 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1554 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1555 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1556 protocol_version = content->negotiated_protocol_version;
1557 return true;
1558 });
1559
1560 return protocol_version;
1561 }
1562
1563 tls_ciphersuite_t
1564 sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_protocol_metadata_t metadata)
1565 {
1566 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0xFFFF);
1567
1568 __block tls_ciphersuite_t negotiated_ciphersuite = SSL_NO_SUCH_CIPHERSUITE;
1569 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1570 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1571 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1572 negotiated_ciphersuite = content->negotiated_ciphersuite;
1573 return true;
1574 });
1575
1576 return negotiated_ciphersuite;
1577 }
1578
1579 SSLCipherSuite
1580 sec_protocol_metadata_get_negotiated_ciphersuite(sec_protocol_metadata_t metadata)
1581 {
1582 return (SSLCipherSuite)sec_protocol_metadata_get_negotiated_tls_ciphersuite(metadata);
1583 }
1584
1585 bool
1586 sec_protocol_metadata_get_early_data_accepted(sec_protocol_metadata_t metadata)
1587 {
1588 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1589
1590 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1591 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1592 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1593 return content->early_data_accepted;
1594 });
1595 }
1596
1597 bool
1598 sec_protocol_metadata_access_supported_signature_algorithms(sec_protocol_metadata_t metadata,
1599 void (^handler)(uint16_t signature_algorithm))
1600 {
1601 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1602 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
1603
1604 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1605 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1606 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1607 if (content->supported_signature_algorithms == NULL) {
1608 return false;
1609 }
1610 xpc_object_t array = content->supported_signature_algorithms;
1611 xpc_array_apply(array, ^bool(__unused size_t index, xpc_object_t _Nonnull value) {
1612 handler((uint16_t)xpc_uint64_get_value(value));
1613 return true;
1614 });
1615 return true;
1616 });
1617 }
1618
1619 bool
1620 sec_protocol_metadata_access_ocsp_response(sec_protocol_metadata_t metadata,
1621 void (^handler)(dispatch_data_t ocsp_data))
1622 {
1623 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1624 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
1625
1626 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1627 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1628 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1629 if (content->ocsp_response == NULL) {
1630 return false;
1631 }
1632 sec_array_t array = content->ocsp_response;
1633 sec_array_apply(array, ^bool(__unused size_t index, sec_object_t object) {
1634 handler((dispatch_data_t)object);
1635 return true;
1636 });
1637 return true;
1638 });
1639 }
1640
1641 bool
1642 sec_protocol_metadata_access_distinguished_names(sec_protocol_metadata_t metadata,
1643 void (^handler)(dispatch_data_t distinguished_name))
1644 {
1645 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1646 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
1647
1648 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1649 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1650 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1651 if (content->distinguished_names == NULL) {
1652 return false;
1653 }
1654 sec_array_t array = content->distinguished_names;
1655 sec_array_apply(array, ^bool(__unused size_t index, sec_object_t object) {
1656 handler((dispatch_data_t)object);
1657 return true;
1658 });
1659 return true;
1660 });
1661 }
1662
1663 static dispatch_data_t
1664 create_dispatch_data_from_xpc_data(xpc_object_t xpc_data)
1665 {
1666 if (!xpc_data) {
1667 return nil;
1668 }
1669
1670 size_t data_len = xpc_data_get_length(xpc_data);
1671 if (data_len == 0) {
1672 return nil;
1673 }
1674
1675 uint8_t *data_buffer = malloc(data_len);
1676 if (!data_buffer) {
1677 return nil;
1678 }
1679
1680 size_t copied_count = xpc_data_get_bytes(xpc_data, data_buffer, 0, data_len);
1681 if (copied_count != data_len) {
1682 free(data_buffer);
1683 return nil;
1684 }
1685
1686 dispatch_data_t data = dispatch_data_create(data_buffer, data_len, NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
1687 free(data_buffer);
1688
1689 return data;
1690 }
1691
1692 bool
1693 sec_protocol_metadata_access_pre_shared_keys(sec_protocol_metadata_t metadata,
1694 void (^handler)(dispatch_data_t psk, dispatch_data_t _Nullable psk_identity))
1695 {
1696 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1697 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
1698
1699 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1700 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1701 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1702 if (content->pre_shared_keys == NULL) {
1703 return false;
1704 }
1705 xpc_array_apply(content->pre_shared_keys, ^bool(size_t index, xpc_object_t _Nonnull tuple) {
1706 if (xpc_array_get_count(tuple) == 2) {
1707 xpc_object_t xpc_psk_data = xpc_array_get_value(tuple, 0);
1708 xpc_object_t xpc_psk_identity_data = xpc_array_get_value(tuple, 1);
1709
1710 dispatch_data_t psk_data = create_dispatch_data_from_xpc_data(xpc_psk_data);
1711 dispatch_data_t psk_identity_data = create_dispatch_data_from_xpc_data(xpc_psk_identity_data);
1712 if (!psk_data || !psk_identity_data) {
1713 // Skip and return early if we can't create a PSK or identity from the provided data. Something's wrong.
1714 return false;
1715 }
1716
1717 handler(psk_data, psk_identity_data);
1718 }
1719 return true;
1720 });
1721 return true;
1722 });
1723 }
1724
1725 static bool
1726 sec_protocol_dispatch_data_are_equal(dispatch_data_t left, dispatch_data_t right)
1727 {
1728 if (!left || !right || left == right) {
1729 return left == right;
1730 }
1731 if (dispatch_data_get_size(left) != dispatch_data_get_size(right)) {
1732 return false;
1733 }
1734
1735 __block bool equal = true;
1736 dispatch_data_apply(left, ^bool(__unused dispatch_data_t _Nonnull lregion, size_t loffset, const void * _Nonnull lbuffer, size_t lsize) {
1737 dispatch_data_apply(right, ^bool(__unused dispatch_data_t _Nonnull rregion, size_t roffset, const void * _Nonnull rbuffer, size_t rsize) {
1738 // There is some overlap
1739 const size_t start = MAX(loffset, roffset);
1740 const size_t end = MIN(loffset + lsize, roffset + rsize);
1741 if (start < end) {
1742 equal = memcmp(&((const uint8_t*)rbuffer)[start - roffset], &((const uint8_t*)lbuffer)[start - loffset], end - start) == 0;
1743 } else {
1744 if (roffset > loffset + lsize) {
1745 // Iteration of right has gone past where we're at on left, bail out of inner apply
1746 // left |---|
1747 // right |---|
1748 return false;
1749 } else if (roffset + rsize < loffset) {
1750 // Iteration of right has not yet reached where we're at on left, keep going
1751 // left |---|
1752 // right |--|
1753 return true;
1754 }
1755 }
1756 return equal;
1757 });
1758 return equal;
1759 });
1760 return equal;
1761 }
1762
1763 static bool
1764 sec_protocol_sec_array_of_dispatch_data_are_equal(sec_array_t arrayA, sec_array_t arrayB)
1765 {
1766 if (sec_array_get_count(arrayA) != sec_array_get_count(arrayB)) {
1767 return false;
1768 }
1769
1770 __block bool equal = true;
1771 (void)sec_array_apply(arrayA, ^bool(size_t indexA, sec_object_t objectA) {
1772 return sec_array_apply(arrayB, ^bool(size_t indexB, sec_object_t objectB) {
1773 if (indexA == indexB) {
1774 dispatch_data_t dataA = (dispatch_data_t)objectA;
1775 dispatch_data_t dataB = (dispatch_data_t)objectB;
1776 equal &= sec_protocol_dispatch_data_are_equal(dataA, dataB);
1777 return equal;
1778 }
1779 return true;
1780 });
1781 });
1782
1783 return equal;
1784 }
1785
1786 static bool
1787 sec_protocol_sec_array_of_sec_certificate_are_equal(sec_array_t arrayA, sec_array_t arrayB)
1788 {
1789 if (sec_array_get_count(arrayA) != sec_array_get_count(arrayB)) {
1790 return false;
1791 }
1792
1793 __block bool equal = true;
1794 (void)sec_array_apply(arrayA, ^bool(size_t indexA, sec_object_t objectA) {
1795 return sec_array_apply(arrayB, ^bool(size_t indexB, sec_object_t objectB) {
1796 if (indexA == indexB) {
1797 sec_certificate_t certA = (sec_certificate_t)objectA;
1798 sec_certificate_t certB = (sec_certificate_t)objectB;
1799
1800 SecCertificateRef certRefA = sec_certificate_copy_ref(certA);
1801 SecCertificateRef certRefB = sec_certificate_copy_ref(certB);
1802
1803 if (certRefA == NULL && certRefB != NULL) {
1804 equal = false;
1805 } else if (certRefA != NULL && certRefB == NULL) {
1806 equal = false;
1807 } else if (certRefA == NULL && certRefB == NULL) {
1808 // pass
1809 } else {
1810 equal &= CFEqual(certRefA, certRefB);
1811 }
1812
1813 CFReleaseSafe(certRefA);
1814 CFReleaseSafe(certRefB);
1815
1816 return equal;
1817 }
1818 return true;
1819 });
1820 });
1821
1822 return equal;
1823 }
1824
1825 static bool
1826 sec_protocol_xpc_object_are_equal(xpc_object_t objectA, xpc_object_t objectB)
1827 {
1828 if (objectA == NULL && objectB != NULL) {
1829 return false;
1830 } else if (objectA != NULL && objectB == NULL) {
1831 return false;
1832 } else if (objectA == NULL && objectB == NULL) {
1833 return true;
1834 } else {
1835 return xpc_equal(objectA, objectB);
1836 }
1837 }
1838
1839 bool
1840 sec_protocol_metadata_peers_are_equal(sec_protocol_metadata_t metadataA, sec_protocol_metadata_t metadataB)
1841 {
1842 SEC_PROTOCOL_METADATA_VALIDATE(metadataA, false);
1843 SEC_PROTOCOL_METADATA_VALIDATE(metadataB, false);
1844
1845 return sec_protocol_metadata_access_handle(metadataA, ^bool(void *handleA) {
1846 sec_protocol_metadata_content_t contentA = (sec_protocol_metadata_content_t)handleA;
1847 SEC_PROTOCOL_METADATA_VALIDATE(contentA, false);
1848
1849 return sec_protocol_metadata_access_handle(metadataB, ^bool(void *handleB) {
1850 sec_protocol_metadata_content_t contentB = (sec_protocol_metadata_content_t)handleB;
1851 SEC_PROTOCOL_METADATA_VALIDATE(contentB, false);
1852
1853 // Relevant peer information includes: Certificate chain, public key, support signature algorithms, OCSP response, and distinguished names
1854 if (!sec_protocol_sec_array_of_sec_certificate_are_equal(contentA->peer_certificate_chain, contentB->peer_certificate_chain)) {
1855 return false;
1856 }
1857 if (!sec_protocol_dispatch_data_are_equal((dispatch_data_t)contentA->peer_public_key, (dispatch_data_t)contentB->peer_public_key)) {
1858 return false;
1859 }
1860 if (!sec_protocol_xpc_object_are_equal((xpc_object_t)contentA->supported_signature_algorithms, (xpc_object_t)contentB->supported_signature_algorithms)) {
1861 return false;
1862 }
1863 if (!sec_protocol_sec_array_of_dispatch_data_are_equal(contentA->ocsp_response, contentB->ocsp_response)) {
1864 return false;
1865 }
1866 if (!sec_protocol_sec_array_of_dispatch_data_are_equal(contentA->distinguished_names, contentB->distinguished_names)) {
1867 return false;
1868 }
1869
1870 return true;
1871 });
1872 });
1873 }
1874
1875 bool
1876 sec_protocol_metadata_challenge_parameters_are_equal(sec_protocol_metadata_t metadataA, sec_protocol_metadata_t metadataB)
1877 {
1878 SEC_PROTOCOL_METADATA_VALIDATE(metadataA, false);
1879 SEC_PROTOCOL_METADATA_VALIDATE(metadataB, false);
1880
1881 return sec_protocol_metadata_access_handle(metadataA, ^bool(void *handleA) {
1882 sec_protocol_metadata_content_t contentA = (sec_protocol_metadata_content_t)handleA;
1883 SEC_PROTOCOL_METADATA_VALIDATE(contentA, false);
1884
1885 return sec_protocol_metadata_access_handle(metadataB, ^bool(void *handleB) {
1886 sec_protocol_metadata_content_t contentB = (sec_protocol_metadata_content_t)handleB;
1887 SEC_PROTOCOL_METADATA_VALIDATE(contentB, false);
1888
1889 if (!sec_protocol_xpc_object_are_equal((xpc_object_t)contentA->supported_signature_algorithms, (xpc_object_t)contentB->supported_signature_algorithms)) {
1890 return false;
1891 }
1892 if (!sec_protocol_sec_array_of_dispatch_data_are_equal(contentA->distinguished_names, contentB->distinguished_names)) {
1893 return false;
1894 }
1895 if (!sec_protocol_dispatch_data_are_equal(contentA->request_certificate_types, contentB->request_certificate_types)) {
1896 return false;
1897 }
1898
1899 return true;
1900 });
1901 });
1902 }
1903
1904 dispatch_data_t
1905 sec_protocol_metadata_create_secret(sec_protocol_metadata_t metadata, size_t label_len,
1906 const char *label, size_t exporter_length)
1907 {
1908 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
1909 SEC_PROTOCOL_METADATA_VALIDATE(label_len, NULL);
1910 SEC_PROTOCOL_METADATA_VALIDATE(label, NULL);
1911 SEC_PROTOCOL_METADATA_VALIDATE(exporter_length, NULL);
1912
1913 __block dispatch_data_t secret = NULL;
1914 sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1915 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1916 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1917
1918 if (content->exporter_function && content->exporter_context) {
1919 sec_protocol_metadata_exporter exporter = (sec_protocol_metadata_exporter)content->exporter_function;
1920 secret = exporter(content->exporter_context, label_len, label, 0, NULL, exporter_length);
1921 }
1922 return true;
1923 });
1924 return secret;
1925 }
1926
1927 dispatch_data_t
1928 sec_protocol_metadata_create_secret_with_context(sec_protocol_metadata_t metadata, size_t label_len,
1929 const char *label, size_t context_len,
1930 const uint8_t *context, size_t exporter_length)
1931 {
1932 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
1933 SEC_PROTOCOL_METADATA_VALIDATE(label_len, NULL);
1934 SEC_PROTOCOL_METADATA_VALIDATE(label, NULL);
1935 SEC_PROTOCOL_METADATA_VALIDATE(context_len, NULL);
1936 SEC_PROTOCOL_METADATA_VALIDATE(context, NULL);
1937 SEC_PROTOCOL_METADATA_VALIDATE(exporter_length, NULL);
1938
1939 __block dispatch_data_t secret = NULL;
1940 sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1941 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1942 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1943
1944 if (content->exporter_function && content->exporter_context) {
1945 sec_protocol_metadata_exporter exporter = (sec_protocol_metadata_exporter)content->exporter_function;
1946 secret = exporter(content->exporter_context, label_len, label, context_len, context, exporter_length);
1947 }
1948 return true;
1949 });
1950 return secret;
1951 }
1952
1953 bool
1954 sec_protocol_metadata_get_tls_false_start_used(sec_protocol_metadata_t metadata)
1955 {
1956 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1957
1958 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1959 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1960 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1961 return content->false_start_used;
1962 });
1963 }
1964
1965 bool
1966 sec_protocol_metadata_get_ticket_offered(sec_protocol_metadata_t metadata)
1967 {
1968 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1969
1970 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1971 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1972 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1973 return content->ticket_offered;
1974 });
1975 }
1976
1977 bool
1978 sec_protocol_metadata_get_ticket_received(sec_protocol_metadata_t metadata)
1979 {
1980 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1981
1982 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1983 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1984 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1985 return content->ticket_received;
1986 });
1987 }
1988
1989 bool
1990 sec_protocol_metadata_get_session_resumed(sec_protocol_metadata_t metadata)
1991 {
1992 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
1993
1994 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
1995 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
1996 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
1997 return content->session_resumed;
1998 });
1999 }
2000
2001 bool
2002 sec_protocol_metadata_get_session_renewed(sec_protocol_metadata_t metadata)
2003 {
2004 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
2005
2006 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2007 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2008 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2009 return content->session_renewed;
2010 });
2011 }
2012
2013 SSLConnectionStrength
2014 sec_protocol_metadata_get_connection_strength(sec_protocol_metadata_t metadata)
2015 {
2016 SEC_PROTOCOL_METADATA_VALIDATE(metadata, SSLConnectionStrengthNonsecure);
2017
2018 __block SSLConnectionStrength strength = SSLConnectionStrengthNonsecure;
2019 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2020 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2021 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2022
2023 // TLSv1.2 and higher are considered strong. Anything less than TLSv1.2 is considered weak at best.
2024 #pragma clang diagnostic push
2025 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2026 SSLProtocol version = content->negotiated_protocol_version;
2027 if (version >= kTLSProtocol12) {
2028 strength = SSLConnectionStrengthStrong;
2029 } else if (version == kTLSProtocol11 || version == kTLSProtocol1) {
2030 strength = SSLConnectionStrengthWeak;
2031 } else {
2032 strength = SSLConnectionStrengthNonsecure;
2033 }
2034
2035 // Legacy ciphersuites make the connection weak, for now. We may consider changing this to nonsecure.
2036 SSLCipherSuite ciphersuite = content->negotiated_ciphersuite;
2037 if (strength != SSLConnectionStrengthNonsecure &&
2038 SSLCiphersuiteGroupContainsCiphersuite(kSSLCiphersuiteGroupLegacy, ciphersuite)) {
2039 strength = SSLConnectionStrengthWeak;
2040 }
2041 #pragma clang diagnostic pop
2042
2043 return true;
2044 });
2045
2046 return strength;
2047 }
2048
2049 dispatch_data_t
2050 sec_protocol_metadata_copy_serialized_session(sec_protocol_metadata_t metadata)
2051 {
2052 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
2053
2054 __block dispatch_data_t session = NULL;
2055 sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2056 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2057 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2058
2059 if (content->session_exporter_function && content->session_exporter_context) {
2060 sec_protocol_metadata_session_exporter exporter = (sec_protocol_metadata_session_exporter)content->session_exporter_function;
2061 session = exporter(content->session_exporter_context);
2062 }
2063 return true;
2064 });
2065 return session;
2066 }
2067
2068 const char * __nullable
2069 sec_protocol_metadata_get_experiment_identifier(sec_protocol_metadata_t metadata)
2070 {
2071 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
2072
2073 __block const char *experiment_identifer = NULL;
2074 sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2075 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2076 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2077
2078 experiment_identifer = content->experiment_identifier;
2079 return true;
2080 });
2081 return experiment_identifer;
2082 }
2083
2084 void
2085 sec_protocol_metadata_copy_connection_id(sec_protocol_metadata_t metadata, uuid_t _Nonnull output_uuid)
2086 {
2087 SEC_PROTOCOL_METADATA_VALIDATE(metadata,);
2088 SEC_PROTOCOL_METADATA_VALIDATE(output_uuid,);
2089
2090 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2091 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2092 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2093
2094 memcpy(output_uuid, content->connection_id, sizeof(content->connection_id));
2095 return true;
2096 });
2097 }
2098
2099 static const char *_options_uint64_keys[] = {
2100 SEC_PROTOCOL_OPTIONS_KEY_min_version,
2101 SEC_PROTOCOL_OPTIONS_KEY_max_version,
2102 SEC_PROTOCOL_OPTIONS_KEY_minimum_rsa_key_size,
2103 SEC_PROTOCOL_OPTIONS_KEY_minimum_ecdsa_key_size,
2104 SEC_PROTOCOL_OPTIONS_KEY_minimum_signature_algorithm,
2105 SEC_PROTOCOL_OPTIONS_KEY_tls_ticket_request_count,
2106 };
2107 static const size_t _options_uint64_keys_len = sizeof(_options_uint64_keys) / sizeof(_options_uint64_keys[0]);
2108
2109 static const char *_options_bool_keys[] = {
2110 SEC_PROTOCOL_OPTIONS_KEY_ats_required,
2111 SEC_PROTOCOL_OPTIONS_KEY_ats_minimum_tls_version_allowed,
2112 SEC_PROTOCOL_OPTIONS_KEY_ats_non_pfs_ciphersuite_allowed,
2113 SEC_PROTOCOL_OPTIONS_KEY_trusted_peer_certificate,
2114 SEC_PROTOCOL_OPTIONS_KEY_disable_sni,
2115 SEC_PROTOCOL_OPTIONS_KEY_enable_fallback_attempt,
2116 SEC_PROTOCOL_OPTIONS_KEY_enable_false_start,
2117 SEC_PROTOCOL_OPTIONS_KEY_enable_tickets,
2118 SEC_PROTOCOL_OPTIONS_KEY_enable_sct,
2119 SEC_PROTOCOL_OPTIONS_KEY_enable_ocsp,
2120 SEC_PROTOCOL_OPTIONS_KEY_enforce_ev,
2121 SEC_PROTOCOL_OPTIONS_KEY_enable_resumption,
2122 SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation,
2123 SEC_PROTOCOL_OPTIONS_KEY_enable_early_data,
2124 SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required,
2125 SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled,
2126 SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled,
2127 SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled,
2128 SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled,
2129 SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled,
2130 SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled,
2131
2132 };
2133 static const size_t _options_bool_keys_len = sizeof(_options_bool_keys) / sizeof(_options_bool_keys[0]);
2134
2135 static bool
2136 _dictionary_has_key(xpc_object_t dict, const char *target_key)
2137 {
2138 if (xpc_get_type(dict) != XPC_TYPE_DICTIONARY) {
2139 return false;
2140 }
2141
2142 return !xpc_dictionary_apply(dict, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
2143 if (strncmp(key, target_key, strlen(target_key)) == 0) {
2144 return false;
2145 }
2146 return true;
2147 });
2148 }
2149
2150 static bool
2151 _options_config_matches_partial_config(xpc_object_t full, xpc_object_t partial)
2152 {
2153 SEC_PROTOCOL_METADATA_VALIDATE(full, false);
2154 SEC_PROTOCOL_METADATA_VALIDATE(partial, false);
2155
2156 return xpc_dictionary_apply(partial, ^bool(const char * _Nonnull entry_key, xpc_object_t _Nonnull value) {
2157 size_t entry_key_len = strnlen(entry_key, MAX_SEC_PROTOCOL_OPTIONS_KEY_LEN);
2158
2159 for (size_t i = 0; i < _options_uint64_keys_len; i++) {
2160 const char *key = _options_uint64_keys[i];
2161 if (strncmp(entry_key, key, MAX(entry_key_len, strlen(key))) == 0) {
2162 if (_dictionary_has_key(full, key)) {
2163 if (xpc_dictionary_get_uint64(full, key) != xpc_dictionary_get_uint64(partial, key)) {
2164 return false;
2165 }
2166 } else {
2167 return false;
2168 }
2169 }
2170 }
2171
2172 for (size_t i = 0; i < _options_bool_keys_len; i++) {
2173 const char *key = _options_bool_keys[i];
2174 if (strncmp(entry_key, key, MAX(entry_key_len, strlen(key))) == 0) {
2175 if (_dictionary_has_key(full, key)) {
2176 if (xpc_dictionary_get_bool(full, key) != xpc_dictionary_get_bool(partial, key)) {
2177 return false;
2178 }
2179 } else {
2180 return false;
2181 }
2182 }
2183 }
2184
2185 return true;
2186 });
2187 }
2188
2189 static bool
2190 _serialize_options(xpc_object_t dictionary, sec_protocol_options_content_t options_content)
2191 {
2192 #define EXPAND_PARAMETER(field) \
2193 SEC_PROTOCOL_OPTIONS_KEY_##field , options_content->field
2194
2195 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(min_version));
2196 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(max_version));
2197 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(minimum_rsa_key_size));
2198 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(minimum_ecdsa_key_size));
2199 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(minimum_signature_algorithm));
2200 xpc_dictionary_set_uint64(dictionary, EXPAND_PARAMETER(tls_ticket_request_count));
2201
2202 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(ats_required));
2203 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(ats_minimum_tls_version_allowed));
2204 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(ats_non_pfs_ciphersuite_allowed));
2205 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(trusted_peer_certificate));
2206 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(disable_sni));
2207 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_fallback_attempt));
2208 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_false_start));
2209 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_tickets));
2210 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_sct));
2211 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_ocsp));
2212 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enforce_ev));
2213 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_resumption));
2214 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_renegotiation));
2215 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_early_data));
2216 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(peer_authentication_required));
2217 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(certificate_compression_enabled));
2218 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_SIKE503_exchange_enabled));
2219 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_HRSS_exchange_enabled));
2220 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(eddsa_enabled));
2221 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_delegated_credentials_enabled));
2222 xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_grease_enabled));
2223
2224 #undef EXPAND_PARAMETER
2225
2226 return true;
2227 }
2228
2229 static struct _options_bool_key_setter {
2230 const char *key;
2231 void (*setter_pointer)(sec_protocol_options_t, bool);
2232 } _options_bool_key_setters[] = {
2233 {
2234 .key = SEC_PROTOCOL_OPTIONS_KEY_ats_required,
2235 .setter_pointer = sec_protocol_options_set_ats_required,
2236 },
2237 {
2238 .key = SEC_PROTOCOL_OPTIONS_KEY_ats_minimum_tls_version_allowed,
2239 .setter_pointer = sec_protocol_options_set_ats_minimum_tls_version_allowed,
2240 },
2241 {
2242 .key = SEC_PROTOCOL_OPTIONS_KEY_ats_non_pfs_ciphersuite_allowed,
2243 .setter_pointer = sec_protocol_options_set_ats_non_pfs_ciphersuite_allowed,
2244 },
2245 {
2246 .key = SEC_PROTOCOL_OPTIONS_KEY_trusted_peer_certificate,
2247 .setter_pointer = sec_protocol_options_set_trusted_peer_certificate,
2248 },
2249 {
2250 .key = SEC_PROTOCOL_OPTIONS_KEY_disable_sni,
2251 .setter_pointer = sec_protocol_options_set_tls_sni_disabled
2252 },
2253 {
2254 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_fallback_attempt,
2255 .setter_pointer = sec_protocol_options_set_tls_is_fallback_attempt,
2256 },
2257 {
2258 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_false_start,
2259 .setter_pointer = sec_protocol_options_set_tls_false_start_enabled,
2260 },
2261 {
2262 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_tickets,
2263 .setter_pointer = sec_protocol_options_set_tls_tickets_enabled,
2264 },
2265 {
2266 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_sct,
2267 .setter_pointer = sec_protocol_options_set_tls_sct_enabled
2268 },
2269 {
2270 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_ocsp,
2271 .setter_pointer = sec_protocol_options_set_tls_ocsp_enabled,
2272 },
2273 {
2274 .key = SEC_PROTOCOL_OPTIONS_KEY_enforce_ev,
2275 .setter_pointer = sec_protocol_options_set_enforce_ev,
2276 },
2277 {
2278 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_resumption,
2279 .setter_pointer = sec_protocol_options_set_tls_resumption_enabled,
2280 },
2281 {
2282 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation,
2283 .setter_pointer = sec_protocol_options_set_tls_renegotiation_enabled,
2284 },
2285 {
2286 .key = SEC_PROTOCOL_OPTIONS_KEY_enable_early_data,
2287 .setter_pointer = sec_protocol_options_set_tls_early_data_enabled,
2288 },
2289 {
2290 .key = SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required,
2291 .setter_pointer = sec_protocol_options_set_peer_authentication_required,
2292 },
2293 {
2294 .key = SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled,
2295 .setter_pointer = sec_protocol_options_set_tls_certificate_compression_enabled,
2296 },
2297 {
2298 .key = SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled,
2299 .setter_pointer = sec_protocol_options_set_tls_SIKE503_exchange_enabled,
2300 },
2301 {
2302 .key = SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled,
2303 .setter_pointer = sec_protocol_options_set_tls_HRSS_exchange_enabled,
2304 },
2305 {
2306 .key = SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled,
2307 .setter_pointer = sec_protocol_options_set_eddsa_enabled,
2308 },
2309 {
2310 .key = SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled,
2311 .setter_pointer = sec_protocol_options_set_tls_delegated_credentials_enabled,
2312 },
2313 {
2314 .key = SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled,
2315 .setter_pointer = sec_protocol_options_set_tls_grease_enabled,
2316 },
2317 };
2318 static const size_t _options_bool_key_setters_len = sizeof(_options_bool_key_setters) / sizeof(_options_bool_key_setters[0]);
2319
2320 static struct _options_uint64_key_setter {
2321 const char *key;
2322 void (*setter_pointer)(sec_protocol_options_t, uint64_t);
2323 } _options_uint64_key_setters[] = {
2324 #pragma clang diagnostic push
2325 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2326 {
2327 .key = SEC_PROTOCOL_OPTIONS_KEY_min_version,
2328 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_tls_min_version
2329 },
2330 {
2331 .key = SEC_PROTOCOL_OPTIONS_KEY_max_version,
2332 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_tls_max_version
2333 },
2334 #pragma clang diagnostic pop
2335 {
2336 .key = SEC_PROTOCOL_OPTIONS_KEY_minimum_rsa_key_size,
2337 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_minimum_rsa_key_size,
2338 },
2339 {
2340 .key = SEC_PROTOCOL_OPTIONS_KEY_minimum_ecdsa_key_size,
2341 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_minimum_ecdsa_key_size,
2342 },
2343 {
2344 .key = SEC_PROTOCOL_OPTIONS_KEY_minimum_signature_algorithm,
2345 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_minimum_signature_algorithm,
2346 },
2347 {
2348 .key = SEC_PROTOCOL_OPTIONS_KEY_tls_ticket_request_count,
2349 .setter_pointer = (void (*)(sec_protocol_options_t, uint64_t))sec_protocol_options_set_tls_ticket_request_count,
2350 },
2351 };
2352 static const size_t _options_uint64_key_setters_len = sizeof(_options_uint64_key_setters) / sizeof(_options_uint64_key_setters[0]);
2353
2354 static bool
2355 _apply_config_options(sec_protocol_options_t options, xpc_object_t config)
2356 {
2357 return sec_protocol_options_access_handle(options, ^bool(void *options_handle) {
2358 sec_protocol_options_content_t options_content = (sec_protocol_options_content_t)options_handle;
2359 SEC_PROTOCOL_METADATA_VALIDATE(options_content, false);
2360 return xpc_dictionary_apply(config, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
2361
2362 size_t key_len = strnlen(key, MAX_SEC_PROTOCOL_OPTIONS_KEY_LEN);
2363 for (size_t i = 0; i < _options_bool_key_setters_len; i++) {
2364 const char *setter_key = _options_bool_key_setters[i].key;
2365 size_t setter_key_len = strnlen(setter_key, MAX_SEC_PROTOCOL_OPTIONS_KEY_LEN);
2366 if (strncmp(setter_key, key, MAX(key_len, setter_key_len)) == 0) {
2367 _options_bool_key_setters[i].setter_pointer(options, xpc_dictionary_get_bool(config, key));
2368 }
2369 }
2370
2371 for (size_t i = 0; i < _options_uint64_key_setters_len; i++) {
2372 const char *setter_key = _options_uint64_key_setters[i].key;
2373 size_t setter_key_len = strnlen(setter_key, MAX_SEC_PROTOCOL_OPTIONS_KEY_LEN);
2374 if (strncmp(setter_key, key, MAX(key_len, setter_key_len)) == 0) {
2375 _options_uint64_key_setters[i].setter_pointer(options, xpc_dictionary_get_uint64(config, key));
2376 }
2377 }
2378
2379 // Now check for ciphersuite options, as these are not expressed via serialized configs
2380 if (strncmp(key, SEC_PROTOCOL_OPTIONS_KEY_ciphersuites, key_len) == 0) {
2381 if (xpc_get_type(value) == XPC_TYPE_ARRAY) {
2382 xpc_array_apply(value, ^bool(size_t index, xpc_object_t _Nonnull ciphersuite_value) {
2383 SSLCipherSuite ciphersuite = (SSLCipherSuite)xpc_array_get_uint64(value, index);
2384 sec_protocol_options_append_tls_ciphersuite(options, ciphersuite);
2385 return true;
2386 });
2387 }
2388 }
2389
2390 return true;
2391 });
2392 });
2393 }
2394
2395 static bool
2396 _serialize_metadata(xpc_object_t dictionary, sec_protocol_metadata_content_t metadata_content)
2397 {
2398 #define xpc_dictionary_set_string_default(d, key, value, default) \
2399 do { \
2400 if (value != NULL) { \
2401 xpc_dictionary_set_string(d, key, value); \
2402 } else { \
2403 xpc_dictionary_set_string(d, key, default); \
2404 } \
2405 } while (0);
2406
2407 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_CIPHERSUITE, metadata_content->negotiated_ciphersuite);
2408 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_PROTOCOL_VERSION, metadata_content->negotiated_protocol_version);
2409 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_TICKET_LIFETIME, metadata_content->ticket_lifetime);
2410
2411 xpc_dictionary_set_string_default(dictionary, SEC_PROTOCOL_METADATA_KEY_PEER_PUBLIC_KEY_TYPE,
2412 metadata_content->peer_public_key_type, SEC_PROTOCOL_METADATA_KEY_DEFAULT_EMPTY_STRING);
2413 xpc_dictionary_set_string_default(dictionary, SEC_PROTOCOL_METADATA_KEY_NEGOTIATED_CURVE,
2414 metadata_content->negotiated_curve, SEC_PROTOCOL_METADATA_KEY_DEFAULT_EMPTY_STRING);
2415 xpc_dictionary_set_string_default(dictionary, SEC_PROTOCOL_METADATA_KEY_PEER_CERTIFICATE_REQUEST_TYPE,
2416 metadata_content->certificate_request_type, SEC_PROTOCOL_METADATA_KEY_DEFAULT_EMPTY_STRING);
2417 xpc_dictionary_set_string_default(dictionary, SEC_PROTOCOL_METADATA_KEY_NEGOTIATED_PROTOCOL,
2418 metadata_content->negotiated_protocol, SEC_PROTOCOL_METADATA_KEY_DEFAULT_EMPTY_STRING);
2419
2420 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_FALSE_START_USED, metadata_content->false_start_used);
2421 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_SESSION_RESUMED, metadata_content->session_resumed);
2422 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_TICKET_OFFERED, metadata_content->ticket_offered);
2423 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_TICKET_RECEIVED, metadata_content->ticket_received);
2424 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_SESSION_RENEWED, metadata_content->session_renewed);
2425 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_RESUMPTION_ATTEMPTED, metadata_content->resumption_attempted);
2426 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_ALPN_USED, metadata_content->alpn_used);
2427 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_NPN_USED, metadata_content->npn_used);
2428 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_OCSP_ENABLED, metadata_content->ocsp_enabled);
2429 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_OCSP_RECEIVED, metadata_content->ocsp_response != NULL);
2430 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_SCT_ENABLED, metadata_content->sct_enabled);
2431 xpc_dictionary_set_bool(dictionary, SEC_PROTOCOL_METADATA_KEY_SCT_RECEIVED, metadata_content->signed_certificate_timestamps != NULL);
2432
2433 #undef xpc_dictionary_set_string_default
2434
2435 return true;
2436 }
2437
2438 static bool
2439 _serialize_success_with_options(xpc_object_t dictionary, sec_protocol_metadata_content_t metadata_content, sec_protocol_options_content_t options_content)
2440 {
2441 if (!_serialize_options(dictionary, options_content)) {
2442 return false;
2443 }
2444 if (!_serialize_metadata(dictionary, metadata_content)) {
2445 return false;
2446 }
2447 return true;
2448 }
2449
2450 static bool
2451 _serialize_failure_with_options(xpc_object_t dictionary, sec_protocol_metadata_content_t metadata_content, sec_protocol_options_content_t options_content)
2452 {
2453 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_ALERT_TYPE, metadata_content->alert_type);
2454 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_ALERT_CODE, metadata_content->alert_code);
2455 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_HANDSHAKE_STATE, metadata_content->handshake_state);
2456 xpc_dictionary_set_uint64(dictionary, SEC_PROTOCOL_METADATA_KEY_FAILURE_STACK_ERROR, metadata_content->stack_error);
2457
2458 return true;
2459 }
2460
2461 xpc_object_t
2462 sec_protocol_metadata_serialize_with_options(sec_protocol_metadata_t metadata, sec_protocol_options_t options)
2463 {
2464 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
2465 SEC_PROTOCOL_METADATA_VALIDATE(options, NULL);
2466
2467 __block xpc_object_t dictionary = xpc_dictionary_create(NULL, NULL, 0);
2468 if (dictionary == NULL) {
2469 return NULL;
2470 }
2471
2472 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2473 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2474 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2475
2476 return sec_protocol_options_access_handle(options, ^bool(void *options_handle) {
2477 sec_protocol_options_content_t options_content = (sec_protocol_options_content_t)options_handle;
2478 SEC_PROTOCOL_METADATA_VALIDATE(options_content, false);
2479
2480 if (metadata_content->failure) {
2481 return _serialize_failure_with_options(dictionary, metadata_content, options_content);
2482 } else {
2483 return _serialize_success_with_options(dictionary, metadata_content, options_content);
2484 }
2485 });
2486 });
2487
2488 return dictionary;
2489 }
2490
2491 dispatch_data_t
2492 sec_protocol_metadata_copy_quic_transport_parameters(sec_protocol_metadata_t metadata)
2493 {
2494 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
2495
2496 __block dispatch_data_t copied_parameters = NULL;
2497 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2498 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2499 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2500 if (metadata_content->quic_transport_parameters) {
2501 copied_parameters = metadata_content->quic_transport_parameters;
2502 dispatch_retain(copied_parameters);
2503 }
2504 return true;
2505 });
2506
2507 return copied_parameters;
2508 }
2509
2510 bool
2511 sec_protocol_metadata_get_tls_certificate_compression_used(sec_protocol_metadata_t metadata)
2512 {
2513 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
2514
2515 __block bool certificate_compression_used = false;
2516 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2517 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2518 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2519 certificate_compression_used = metadata_content->certificate_compression_used;
2520 return true;
2521 });
2522
2523 return certificate_compression_used;
2524 }
2525
2526 uint16_t
2527 sec_protocol_metadata_get_tls_certificate_compression_algorithm(sec_protocol_metadata_t metadata)
2528 {
2529 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
2530
2531 __block uint16_t certificate_compression_algorithm = 0;
2532 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2533 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2534 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2535 certificate_compression_algorithm = metadata_content->certificate_compression_algorithm;
2536 return true;
2537 });
2538
2539 return certificate_compression_algorithm;
2540 }
2541
2542 uint64_t
2543 sec_protocol_metadata_get_handshake_rtt(sec_protocol_metadata_t metadata)
2544 {
2545 SEC_PROTOCOL_METADATA_VALIDATE(metadata, 0);
2546
2547 __block uint64_t rtt = 0;
2548 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2549 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2550 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2551 rtt = metadata_content->handshake_rtt;
2552 return true;
2553 });
2554
2555 return rtt;
2556 }
2557
2558 sec_trust_t
2559 sec_protocol_metadata_copy_sec_trust(sec_protocol_metadata_t metadata)
2560 {
2561 SEC_PROTOCOL_METADATA_VALIDATE(metadata, nil);
2562
2563 __block sec_trust_t trust = nil;
2564 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2565 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2566 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2567 if (metadata_content->trust_ref != nil) {
2568 trust = metadata_content->trust_ref;
2569 sec_retain(trust);
2570 }
2571 return true;
2572 });
2573
2574 return trust;
2575 }
2576
2577 sec_identity_t
2578 sec_protocol_metadata_copy_sec_identity(sec_protocol_metadata_t metadata)
2579 {
2580 SEC_PROTOCOL_METADATA_VALIDATE(metadata, nil);
2581
2582 __block sec_identity_t identity = nil;
2583 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *metadata_handle) {
2584 sec_protocol_metadata_content_t metadata_content = (sec_protocol_metadata_content_t)metadata_handle;
2585 SEC_PROTOCOL_METADATA_VALIDATE(metadata_content, false);
2586 if (metadata_content->identity != nil) {
2587 identity = metadata_content->identity;
2588 sec_retain(identity);
2589 }
2590 return true;
2591 });
2592
2593 return identity;
2594 }
2595
2596 bool
2597 sec_protocol_metadata_access_sent_certificates(sec_protocol_metadata_t metadata,
2598 void (^handler)(sec_certificate_t certificate))
2599 {
2600 SEC_PROTOCOL_METADATA_VALIDATE(metadata, false);
2601 SEC_PROTOCOL_METADATA_VALIDATE(handler, false);
2602
2603 return sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2604 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2605 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2606
2607 if (content->identity != nil && sec_identity_has_certificates(content->identity)) {
2608 return sec_identity_access_certificates(content->identity, handler);
2609 }
2610
2611 if (content->sent_certificate_chain != NULL) {
2612 return sec_array_apply(content->sent_certificate_chain, ^bool(__unused size_t index, sec_object_t object) {
2613 handler((sec_certificate_t)object);
2614 return true;
2615 });
2616 }
2617
2618 return false;
2619 });
2620 }
2621
2622 const char *
2623 sec_protocol_metadata_get_tls_negotiated_group(sec_protocol_metadata_t metadata)
2624 {
2625 SEC_PROTOCOL_METADATA_VALIDATE(metadata, NULL);
2626
2627 __block const char *negotiated_curve = NULL;
2628 (void)sec_protocol_metadata_access_handle(metadata, ^bool(void *handle) {
2629 sec_protocol_metadata_content_t content = (sec_protocol_metadata_content_t)handle;
2630 SEC_PROTOCOL_METADATA_VALIDATE(content, false);
2631 negotiated_curve = content->negotiated_curve;
2632 return true;
2633 });
2634
2635 return negotiated_curve;
2636 }
2637
2638 void *
2639 sec_retain(void *obj)
2640 {
2641 if (obj != NULL) {
2642 return os_retain(obj);
2643 } else {
2644 return NULL;
2645 }
2646 }
2647
2648 void
2649 sec_release(void *obj)
2650 {
2651 if (obj != NULL) {
2652 os_release(obj);
2653 }
2654 }
2655
2656 xpc_object_t
2657 sec_protocol_options_create_config(sec_protocol_options_t options)
2658 {
2659 SEC_PROTOCOL_METADATA_VALIDATE(options, NULL);
2660
2661 __block xpc_object_t dictionary = xpc_dictionary_create(NULL, NULL, 0);
2662 if (dictionary == NULL) {
2663 return NULL;
2664 }
2665
2666 bool serialized = sec_protocol_options_access_handle(options, ^bool(void *options_handle) {
2667 sec_protocol_options_content_t options_content = (sec_protocol_options_content_t)options_handle;
2668 SEC_PROTOCOL_METADATA_VALIDATE(options_content, false);
2669
2670 return _serialize_options(dictionary, options_content);
2671 });
2672
2673 if (serialized) {
2674 return dictionary; // retained reference
2675 } else {
2676 xpc_release(dictionary);
2677 return NULL;
2678 }
2679 }
2680
2681 bool
2682 sec_protocol_options_matches_config(sec_protocol_options_t options, xpc_object_t config)
2683 {
2684 SEC_PROTOCOL_METADATA_VALIDATE(options, false);
2685 SEC_PROTOCOL_METADATA_VALIDATE(config, false);
2686
2687 if (xpc_get_type(config) != XPC_TYPE_DICTIONARY) {
2688 return false;
2689 }
2690
2691 xpc_object_t options_config = sec_protocol_options_create_config(options);
2692 if (options_config == NULL) {
2693 return false;
2694 }
2695
2696 bool match = _options_config_matches_partial_config(options_config, config);
2697 xpc_release(options_config);
2698
2699 return match;
2700 }
2701
2702 bool
2703 sec_protocol_options_apply_config(sec_protocol_options_t options, xpc_object_t config)
2704 {
2705 SEC_PROTOCOL_METADATA_VALIDATE(options, false);
2706 SEC_PROTOCOL_METADATA_VALIDATE(config, false);
2707
2708 if (xpc_get_type(config) != XPC_TYPE_DICTIONARY) {
2709 return false;
2710 }
2711
2712 return _apply_config_options(options, config);
2713 }