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