]> git.saurik.com Git - apple/security.git/blob - protocol/SecProtocolTypes.m
Security-59306.11.20.tar.gz
[apple/security.git] / protocol / SecProtocolTypes.m
1 //
2 // SecProtocolTypes.m
3 // Security
4 //
5
6 #import "utilities/SecCFRelease.h"
7 #import "utilities/SecCFWrappers.h"
8
9 #define OS_OBJECT_HAVE_OBJC_SUPPORT 1
10
11 #define SEC_NULL_BAD_INPUT ((void *_Nonnull)NULL)
12 #define SEC_NULL_OUT_OF_MEMORY SEC_NULL_BAD_INPUT
13
14 #define SEC_NIL_BAD_INPUT ((void *_Nonnull)nil)
15 #define SEC_NIL_OUT_OF_MEMORY SEC_NIL_BAD_INPUT
16
17 #define SEC_CONCRETE_CLASS_NAME(external_type) SecConcrete_##external_type
18 #define SEC_CONCRETE_PREFIX_STR "SecConcrete_"
19
20 #define SEC_OBJECT_DECL_INTERNAL_OBJC(external_type) \
21 @class SEC_CONCRETE_CLASS_NAME(external_type); \
22 typedef SEC_CONCRETE_CLASS_NAME(external_type) *external_type##_t
23
24 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, visibility, ...) \
25 @protocol OS_OBJECT_CLASS(external_type) <_protocol> \
26 @end \
27 visibility \
28 @interface SEC_CONCRETE_CLASS_NAME(external_type) : NSObject<OS_OBJECT_CLASS(external_type)> \
29 _Pragma("clang diagnostic push") \
30 _Pragma("clang diagnostic ignored \"-Wobjc-interface-ivars\"") \
31 __VA_ARGS__ \
32 _Pragma("clang diagnostic pop") \
33 @end \
34 typedef int _useless_typedef_oio_##external_type
35
36 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, _protocol, ...) \
37 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, ,__VA_ARGS__)
38
39 #define SEC_OBJECT_IMPL_INTERNAL_OBJC(external_type, ...) \
40 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, NSObject, ##__VA_ARGS__)
41
42 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_VISIBILITY(external_type, visibility, ...) \
43 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, NSObject, visibility, ##__VA_ARGS__)
44
45 #define SEC_OBJECT_IMPL 1
46
47 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_array);
48 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_identity);
49 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_trust);
50 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_certificate);
51 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_configuration_builder);
52 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_object);
53 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_options);
54 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_metadata);
55 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_configuration);
56
57 #import "SecProtocolInternal.h"
58 #import <Security/SecProtocolPriv.h>
59 #import "SecProtocolTypesPriv.h"
60
61 #import <Foundation/Foundation.h>
62 #import <CoreFoundation/CoreFoundation.h>
63 #import <CoreFoundation/CFPriv.h>
64
65 #import <os/log.h>
66 #import <xpc/private.h>
67
68 #import <os/object.h>
69
70 #ifndef SEC_ANALYZER_HIDE_DEADSTORE
71 # ifdef __clang_analyzer__
72 # define SEC_ANALYZER_HIDE_DEADSTORE(var) do { if (var) {} } while (0)
73 # else // __clang_analyzer__
74 # define SEC_ANALYZER_HIDE_DEADSTORE(var) do {} while (0)
75 # endif // __clang_analyzer__
76 #endif // SEC_ANALYZER_HIDE_DEADSTORE
77
78 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_array,
79 {
80 xpc_object_t xpc_array;
81 });
82
83 @implementation SEC_CONCRETE_CLASS_NAME(sec_array)
84
85 - (instancetype)init
86 {
87 self = [super init];
88 if (self == nil) {
89 return SEC_NIL_OUT_OF_MEMORY;
90 }
91 self->xpc_array = xpc_array_create(NULL, 0);
92 return self;
93 }
94
95 - (void)dealloc
96 {
97 if (self->xpc_array != nil) {
98 xpc_array_apply(self->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
99 void *pointer = xpc_array_get_pointer(self->xpc_array, index);
100 sec_object_t object = (sec_object_t)CFBridgingRelease(pointer);
101 SEC_ANALYZER_HIDE_DEADSTORE(object);
102 object = nil;
103 return true;
104 });
105 self->xpc_array = nil;
106 }
107 }
108
109 sec_array_t
110 sec_array_create(void)
111 {
112 return [[SEC_CONCRETE_CLASS_NAME(sec_array) alloc] init];
113 }
114
115 void
116 sec_array_append(sec_array_t array, sec_object_t object)
117 {
118 if (array != NULL &&
119 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY &&
120 object != NULL) {
121 void *retained_pointer = __DECONST(void *, CFBridgingRetain(object));
122 xpc_array_set_pointer(array->xpc_array, XPC_ARRAY_APPEND, retained_pointer);
123 // 'Leak' the retain, and save the pointer into the array
124 }
125 }
126
127 size_t
128 sec_array_get_count(sec_array_t array)
129 {
130 if (array != NULL &&
131 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
132 return xpc_array_get_count(array->xpc_array);
133 }
134 return 0;
135 }
136
137 bool
138 sec_array_apply(sec_array_t array, sec_array_applier_t applier)
139 {
140 if (array != NULL &&
141 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
142 return xpc_array_apply(array->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
143 void *pointer = xpc_array_get_pointer(array->xpc_array, index);
144 return applier(index, (__bridge sec_object_t)(pointer));
145 });
146 }
147 return false;
148 }
149
150 @end
151
152 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity,
153 {
154 SecIdentityRef identity;
155 CFArrayRef certs;
156 sec_protocol_private_key_sign_t sign_block;
157 sec_protocol_private_key_decrypt_t decrypt_block;
158 dispatch_queue_t operation_queue;
159 });
160
161 @implementation SEC_CONCRETE_CLASS_NAME(sec_identity)
162
163 - (instancetype)initWithIdentity:(SecIdentityRef)_identity
164 {
165 if (_identity == NULL) {
166 return SEC_NIL_BAD_INPUT;
167 }
168
169 self = [super init];
170 if (self == nil) {
171 return SEC_NIL_OUT_OF_MEMORY;
172 }
173 self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
174 return self;
175 }
176
177 - (instancetype)initWithIdentityAndCertificates:(SecIdentityRef)_identity certificates:(CFArrayRef)certificates
178 {
179 if (_identity == NULL) {
180 return SEC_NIL_BAD_INPUT;
181 }
182
183 self = [super init];
184 if (self == nil) {
185 return SEC_NIL_OUT_OF_MEMORY;
186 }
187 self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
188 self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates));
189
190 return self;
191 }
192
193 - (instancetype)initWithCertificates:(CFArrayRef)certificates signBlock:(sec_protocol_private_key_sign_t)sign decryptBlock:(sec_protocol_private_key_decrypt_t)decrypt queue:(dispatch_queue_t)queue
194 {
195 if (certificates == NULL) {
196 return SEC_NIL_BAD_INPUT;
197 }
198 if (sign == NULL) {
199 return SEC_NIL_BAD_INPUT;
200 }
201 if (decrypt == NULL) {
202 return SEC_NIL_BAD_INPUT;
203 }
204
205 self = [super init];
206 if (self == nil) {
207 return SEC_NIL_OUT_OF_MEMORY;
208 }
209
210 self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates));
211 self->sign_block = sign;
212 self->decrypt_block = decrypt;
213 self->operation_queue = queue;
214
215 return self;
216 }
217
218 - (void)dealloc
219 {
220 if (self->identity != NULL) {
221 CFRelease(self->identity);
222 self->identity = NULL;
223
224 if (self->certs) {
225 CFRelease(self->certs);
226 }
227 self->certs = NULL;
228 }
229 }
230
231 sec_identity_t
232 sec_identity_create(SecIdentityRef identity)
233 {
234 return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentity:identity];
235 }
236
237 sec_identity_t
238 sec_identity_create_with_certificates(SecIdentityRef identity, CFArrayRef certificates)
239 {
240 return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentityAndCertificates:identity certificates:certificates];
241 }
242
243 sec_identity_t
244 sec_identity_create_with_certificates_and_external_private_key(CFArrayRef __nonnull certificates,
245 sec_protocol_private_key_sign_t sign_block,
246 sec_protocol_private_key_decrypt_t decrypt_block,
247 dispatch_queue_t queue)
248 {
249 return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithCertificates:certificates signBlock:sign_block decryptBlock:decrypt_block queue:queue];
250 }
251
252 SecIdentityRef
253 sec_identity_copy_ref(sec_identity_t object)
254 {
255 if (object == NULL) {
256 return SEC_NULL_BAD_INPUT;
257 }
258 if (object->identity != NULL) {
259 return __DECONST(SecIdentityRef, CFRetain(object->identity));
260 }
261 return SEC_NULL_BAD_INPUT;
262 }
263
264 CFArrayRef
265 sec_identity_copy_certificates_ref(sec_identity_t object)
266 {
267 if (object == NULL) {
268 return SEC_NULL_BAD_INPUT;
269 }
270 if (object->certs != NULL) {
271 return __DECONST(CFArrayRef, CFRetain(object->certs));
272 }
273 return SEC_NULL_BAD_INPUT;
274 }
275
276 bool
277 sec_identity_access_certificates(sec_identity_t identity,
278 void (^handler)(sec_certificate_t certificate))
279 {
280 if (identity == NULL) {
281 return false;
282 }
283 if (identity->certs != NULL) {
284 CFArrayForEach(identity->certs, ^(const void *value) {
285 SecCertificateRef certificate_ref = (SecCertificateRef)value;
286 if (certificate_ref != NULL) {
287 sec_certificate_t certificate = sec_certificate_create(certificate_ref);
288 handler(certificate);
289 }
290 });
291 return true;
292 }
293 return false;
294 }
295
296 bool
297 sec_identity_has_certificates(sec_identity_t identity)
298 {
299 if (identity == NULL) {
300 return false;
301 }
302 return identity->certs != NULL;
303 }
304
305 sec_protocol_private_key_sign_t
306 sec_identity_copy_private_key_sign_block(sec_identity_t object)
307 {
308 if (object == NULL) {
309 return SEC_NULL_BAD_INPUT;
310 }
311 if (object->sign_block != NULL) {
312 return object->sign_block;
313 }
314 return SEC_NIL_BAD_INPUT;
315 }
316
317 sec_protocol_private_key_decrypt_t
318 sec_identity_copy_private_key_decrypt_block(sec_identity_t object)
319 {
320 if (object == NULL) {
321 return SEC_NULL_BAD_INPUT;
322 }
323 if (object->decrypt_block != NULL) {
324 return object->decrypt_block;
325 }
326 return SEC_NIL_BAD_INPUT;
327 }
328
329 dispatch_queue_t
330 sec_identity_copy_private_key_queue(sec_identity_t object)
331 {
332 if (object == NULL) {
333 return SEC_NULL_BAD_INPUT;
334 }
335 if (object->operation_queue != nil) {
336 return object->operation_queue;
337 }
338 return SEC_NIL_BAD_INPUT;
339 }
340
341
342 @end
343
344 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_certificate,
345 {
346 SecCertificateRef certificate;
347 });
348
349 @implementation SEC_CONCRETE_CLASS_NAME(sec_certificate)
350
351 - (instancetype)initWithCertificate:(SecCertificateRef)_certificate
352 {
353 if (_certificate == NULL) {
354 return SEC_NIL_BAD_INPUT;
355 }
356
357 self = [super init];
358 if (self == nil) {
359 return SEC_NIL_OUT_OF_MEMORY;
360 }
361 self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate));
362 return self;
363 }
364
365 - (void)dealloc
366 {
367 if (self->certificate != NULL) {
368 CFRelease(self->certificate);
369 self->certificate = NULL;
370 }
371 }
372
373 sec_certificate_t
374 sec_certificate_create(SecCertificateRef certificate)
375 {
376 return [[SEC_CONCRETE_CLASS_NAME(sec_certificate) alloc] initWithCertificate:certificate];
377 }
378
379 SecCertificateRef
380 sec_certificate_copy_ref(sec_certificate_t object)
381 {
382 if (object == NULL) {
383 return SEC_NULL_BAD_INPUT;
384 }
385 if (object->certificate != NULL) {
386 return __DECONST(SecCertificateRef, CFRetain(object->certificate));
387 }
388 return SEC_NULL_BAD_INPUT;
389 }
390
391 @end
392
393 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_trust,
394 {
395 SecTrustRef trust;
396 });
397
398 @implementation SEC_CONCRETE_CLASS_NAME(sec_trust)
399
400 - (instancetype)initWithTrust:(SecTrustRef)_trust
401 {
402 if (_trust == NULL) {
403 return SEC_NIL_BAD_INPUT;
404 }
405
406 self = [super init];
407 if (self == nil) {
408 return SEC_NIL_OUT_OF_MEMORY;
409 }
410 self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust));
411 return self;
412 }
413
414 - (void)dealloc
415 {
416 if (self->trust != NULL) {
417 CFRelease(self->trust);
418 self->trust = NULL;
419 }
420 }
421
422 sec_trust_t
423 sec_trust_create(SecTrustRef trust)
424 {
425 return [[SEC_CONCRETE_CLASS_NAME(sec_trust) alloc] initWithTrust:trust];
426 }
427
428 SecTrustRef
429 sec_trust_copy_ref(sec_trust_t object)
430 {
431 if (object == NULL) {
432 return SEC_NULL_BAD_INPUT;
433 }
434 if (object->trust != NULL) {
435 return __DECONST(SecTrustRef, CFRetain(object->trust));
436 }
437 return SEC_NULL_BAD_INPUT;
438 }
439
440 @end
441
442 static bool
443 _is_apple_bundle(void)
444 {
445 static dispatch_once_t onceToken;
446 static bool result = false;
447 dispatch_once(&onceToken, ^{
448 CFBundleRef bundle = CFBundleGetMainBundle();
449 CFStringRef bundleID = CFBundleGetIdentifier(bundle);
450 result = !bundleID || CFStringHasPrefix(bundleID, CFSTR("com.apple."));
451 });
452 return result;
453 }
454
455 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration_builder,
456 {
457 @package
458 CFDictionaryRef dictionary;
459 bool is_apple;
460 });
461
462 @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration_builder)
463
464 - (id)init {
465 self = [super init];
466 if (self) {
467 CFBundleRef bundle = CFBundleGetMainBundle();
468 if (bundle != NULL) {
469 CFTypeRef rawATS = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR(kATSInfoKey));
470 self->dictionary = (CFDictionaryRef)rawATS;
471 CFRetainSafe(self->dictionary);
472 self->is_apple = _is_apple_bundle();
473 }
474 }
475 return self;
476 }
477
478 - (id)initWithDictionary:(CFDictionaryRef)dict andInternalFlag:(bool)flag {
479 self = [super init];
480 if (self) {
481 self->dictionary = dict;
482 CFRetainSafe(dict);
483 self->is_apple = flag;
484 }
485 return self;
486 }
487
488 @end
489
490 sec_protocol_configuration_builder_t
491 sec_protocol_configuration_builder_copy_default()
492 {
493 return [[SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration_builder) alloc] init];
494 }
495
496 sec_protocol_configuration_builder_t
497 sec_protocol_configuration_builder_create(CFDictionaryRef dictionary, bool is_apple)
498 {
499 return [[SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration_builder) alloc] initWithDictionary:dictionary andInternalFlag:is_apple];
500 }
501
502 CFDictionaryRef
503 sec_protocol_configuration_builder_get_ats_dictionary(sec_protocol_configuration_builder_t builder)
504 {
505 return builder->dictionary;
506 }
507
508 bool
509 sec_protocol_configuration_builder_get_is_apple_bundle(sec_protocol_configuration_builder_t builder)
510 {
511 return builder->is_apple;
512 }
513
514 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration,
515 {
516 xpc_object_t dictionary;
517 });
518
519 @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration)
520
521 - (id)init {
522 self = [super init];
523 if (self) {
524 self->dictionary = xpc_dictionary_create(NULL, NULL, 0);
525 }
526 return self;
527 }
528
529 static sec_protocol_configuration_t
530 sec_protocol_configuration_create(void)
531 {
532 return [[SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration) alloc] init];
533 }
534
535 sec_protocol_configuration_t
536 sec_protocol_configuration_create_with_builder(sec_protocol_configuration_builder_t builder)
537 {
538 sec_protocol_configuration_t configuration = sec_protocol_configuration_create();
539 if (configuration) {
540 if (builder->is_apple) {
541 os_log_debug(OS_LOG_DEFAULT, "Building default configuration for first-party bundle");
542 sec_protocol_configuration_populate_insecure_defaults(configuration);
543 } else {
544 os_log_debug(OS_LOG_DEFAULT, "Building default configuration for third-party bundle");
545 sec_protocol_configuration_populate_secure_defaults(configuration);
546 }
547
548 sec_protocol_configuration_register_builtin_exceptions(configuration);
549 CFDictionaryRef dictionary = builder->dictionary;
550 if (dictionary) {
551 os_log_debug(OS_LOG_DEFAULT, "Setting configuration overrides based on AppTransportSecurity exceptions");
552 sec_protocol_configuration_set_ats_overrides(configuration, dictionary);
553 } else {
554 os_log_debug(OS_LOG_DEFAULT, "Using default configuration settings");
555 }
556 } else {
557 os_log_error(OS_LOG_DEFAULT, "sec_protocol_configuration_create failed");
558 }
559 return configuration;
560 }
561
562 xpc_object_t
563 sec_protocol_configuration_get_map(sec_protocol_configuration_t configuration)
564 {
565 return configuration->dictionary;
566 }
567
568 @end