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