]> git.saurik.com Git - apple/security.git/blob - protocol/SecProtocolTypes.m
Security-58286.200.222.tar.gz
[apple/security.git] / protocol / SecProtocolTypes.m
1 //
2 // SecProtocolTypes.m
3 // Security
4 //
5
6 #include "utilities/SecCFRelease.h"
7
8 #define OS_OBJECT_HAVE_OBJC_SUPPORT 1
9
10 #define SEC_NULL_BAD_INPUT ((void *_Nonnull)NULL)
11 #define SEC_NULL_OUT_OF_MEMORY SEC_NULL_BAD_INPUT
12
13 #define SEC_NIL_BAD_INPUT ((void *_Nonnull)nil)
14 #define SEC_NIL_OUT_OF_MEMORY SEC_NIL_BAD_INPUT
15
16 #define SEC_CONCRETE_CLASS_NAME(external_type) SecConcrete_##external_type
17 #define SEC_CONCRETE_PREFIX_STR "SecConcrete_"
18
19 #define SEC_OBJECT_DECL_INTERNAL_OBJC(external_type) \
20 @class SEC_CONCRETE_CLASS_NAME(external_type); \
21 typedef SEC_CONCRETE_CLASS_NAME(external_type) *external_type##_t
22
23 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, visibility, ...) \
24 @protocol OS_OBJECT_CLASS(external_type) <_protocol> \
25 @end \
26 visibility \
27 @interface SEC_CONCRETE_CLASS_NAME(external_type) : NSObject<OS_OBJECT_CLASS(external_type)> \
28 _Pragma("clang diagnostic push") \
29 _Pragma("clang diagnostic ignored \"-Wobjc-interface-ivars\"") \
30 __VA_ARGS__ \
31 _Pragma("clang diagnostic pop") \
32 @end \
33 typedef int _useless_typedef_oio_##external_type
34
35 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, _protocol, ...) \
36 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, _protocol, ,__VA_ARGS__)
37
38 #define SEC_OBJECT_IMPL_INTERNAL_OBJC(external_type, ...) \
39 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL(external_type, NSObject, ##__VA_ARGS__)
40
41 #define SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_VISIBILITY(external_type, visibility, ...) \
42 SEC_OBJECT_IMPL_INTERNAL_OBJC_WITH_PROTOCOL_AND_VISBILITY(external_type, NSObject, visibility, ##__VA_ARGS__)
43
44 #define SEC_OBJECT_IMPL 1
45
46 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_array);
47 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_identity);
48 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_trust);
49 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_certificate);
50 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_tls_extension);
51 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_object);
52 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_options);
53 SEC_OBJECT_DECL_INTERNAL_OBJC(sec_protocol_metadata);
54
55 #import <Security/SecProtocolPriv.h>
56
57 #import <Foundation/Foundation.h>
58 #import <CoreFoundation/CoreFoundation.h>
59 #import <os/log.h>
60 #import <xpc/private.h>
61
62 #import <os/object.h>
63
64 #ifndef SEC_ANALYZER_HIDE_DEADSTORE
65 # ifdef __clang_analyzer__
66 # define SEC_ANALYZER_HIDE_DEADSTORE(var) do { if (var) {} } while (0)
67 # else // __clang_analyzer__
68 # define SEC_ANALYZER_HIDE_DEADSTORE(var) do {} while (0)
69 # endif // __clang_analyzer__
70 #endif // SEC_ANALYZER_HIDE_DEADSTORE
71
72 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_array,
73 {
74 xpc_object_t xpc_array;
75 });
76
77 @implementation SEC_CONCRETE_CLASS_NAME(sec_array)
78
79 - (instancetype)init
80 {
81 self = [super init];
82 if (self == nil) {
83 return SEC_NIL_OUT_OF_MEMORY;
84 }
85 self->xpc_array = xpc_array_create(NULL, 0);
86 return self;
87 }
88
89 - (void)dealloc
90 {
91 if (self->xpc_array != nil) {
92 xpc_array_apply(self->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
93 void *pointer = xpc_array_get_pointer(self->xpc_array, index);
94 sec_object_t object = (sec_object_t)CFBridgingRelease(pointer);
95 SEC_ANALYZER_HIDE_DEADSTORE(object);
96 object = nil;
97 return true;
98 });
99 self->xpc_array = nil;
100 }
101 }
102
103 sec_array_t
104 sec_array_create(void)
105 {
106 return [[SEC_CONCRETE_CLASS_NAME(sec_array) alloc] init];
107 }
108
109 void
110 sec_array_append(sec_array_t array, sec_object_t object)
111 {
112 if (array != NULL &&
113 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY &&
114 object != NULL) {
115 void *retained_pointer = __DECONST(void *, CFBridgingRetain(object));
116 xpc_array_set_pointer(array->xpc_array, XPC_ARRAY_APPEND, retained_pointer);
117 // 'Leak' the retain, and save the pointer into the array
118 }
119 }
120
121 size_t
122 sec_array_get_count(sec_array_t array)
123 {
124 if (array != NULL &&
125 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
126 return xpc_array_get_count(array->xpc_array);
127 }
128 return 0;
129 }
130
131 bool
132 sec_array_apply(sec_array_t array, sec_array_applier_t applier)
133 {
134 if (array != NULL &&
135 array->xpc_array != NULL && xpc_get_type(array->xpc_array) == XPC_TYPE_ARRAY) {
136 return xpc_array_apply(array->xpc_array, ^bool(size_t index, __unused xpc_object_t value) {
137 void *pointer = xpc_array_get_pointer(array->xpc_array, index);
138 return applier(index, (__bridge sec_object_t)(pointer));
139 });
140 }
141 return false;
142 }
143
144 @end
145
146 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity,
147 {
148 SecIdentityRef identity;
149 CFArrayRef certs;
150 });
151
152 @implementation SEC_CONCRETE_CLASS_NAME(sec_identity)
153
154 - (instancetype)initWithIdentity:(SecIdentityRef)_identity
155 {
156 if (_identity == NULL) {
157 return SEC_NIL_BAD_INPUT;
158 }
159
160 self = [super init];
161 if (self == nil) {
162 return SEC_NIL_OUT_OF_MEMORY;
163 }
164 self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
165 return self;
166 }
167
168 - (instancetype)initWithIdentityAndCertificates:(SecIdentityRef)_identity certificates:(CFArrayRef)certificates
169 {
170 if (_identity == NULL) {
171 return SEC_NIL_BAD_INPUT;
172 }
173
174 self = [super init];
175 if (self == nil) {
176 return SEC_NIL_OUT_OF_MEMORY;
177 }
178 self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity));
179 self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates));
180
181 return self;
182 }
183
184 - (void)dealloc
185 {
186 if (self->identity != NULL) {
187 CFRelease(self->identity);
188 self->identity = NULL;
189
190 if (self->certs) {
191 CFRelease(self->certs);
192 }
193 self->certs = NULL;
194 }
195 }
196
197 sec_identity_t
198 sec_identity_create(SecIdentityRef identity)
199 {
200 return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentity:identity];
201 }
202
203 sec_identity_t
204 sec_identity_create_with_certificates(SecIdentityRef identity, CFArrayRef certificates)
205 {
206 return [[SEC_CONCRETE_CLASS_NAME(sec_identity) alloc] initWithIdentityAndCertificates:identity certificates:certificates];
207 }
208
209 SecIdentityRef
210 sec_identity_copy_ref(sec_identity_t object)
211 {
212 if (object == NULL) {
213 return SEC_NULL_BAD_INPUT;
214 }
215 if (object->identity != NULL) {
216 return __DECONST(SecIdentityRef, CFRetain(object->identity));
217 }
218 return SEC_NULL_BAD_INPUT;
219 }
220
221 CFArrayRef
222 sec_identity_copy_certificates_ref(sec_identity_t object)
223 {
224 if (object == NULL) {
225 return SEC_NULL_BAD_INPUT;
226 }
227 if (object->certs != NULL) {
228 return __DECONST(CFArrayRef, CFRetain(object->certs));
229 }
230 return SEC_NULL_BAD_INPUT;
231 }
232
233 @end
234
235 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_certificate,
236 {
237 SecCertificateRef certificate;
238 });
239
240 @implementation SEC_CONCRETE_CLASS_NAME(sec_certificate)
241
242 - (instancetype)initWithCertificate:(SecCertificateRef)_certificate
243 {
244 if (_certificate == NULL) {
245 return SEC_NIL_BAD_INPUT;
246 }
247
248 self = [super init];
249 if (self == nil) {
250 return SEC_NIL_OUT_OF_MEMORY;
251 }
252 self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate));
253 return self;
254 }
255
256 - (void)dealloc
257 {
258 if (self->certificate != NULL) {
259 CFRelease(self->certificate);
260 self->certificate = NULL;
261 }
262 }
263
264 sec_certificate_t
265 sec_certificate_create(SecCertificateRef certificate)
266 {
267 return [[SEC_CONCRETE_CLASS_NAME(sec_certificate) alloc] initWithCertificate:certificate];
268 }
269
270 SecCertificateRef
271 sec_certificate_copy_ref(sec_certificate_t object)
272 {
273 if (object == NULL) {
274 return SEC_NULL_BAD_INPUT;
275 }
276 if (object->certificate != NULL) {
277 return __DECONST(SecCertificateRef, CFRetain(object->certificate));
278 }
279 return SEC_NULL_BAD_INPUT;
280 }
281
282 @end
283
284 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_trust,
285 {
286 SecTrustRef trust;
287 });
288
289 @implementation SEC_CONCRETE_CLASS_NAME(sec_trust)
290
291 - (instancetype)initWithTrust:(SecTrustRef)_trust
292 {
293 if (_trust == NULL) {
294 return SEC_NIL_BAD_INPUT;
295 }
296
297 self = [super init];
298 if (self == nil) {
299 return SEC_NIL_OUT_OF_MEMORY;
300 }
301 self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust));
302 return self;
303 }
304
305 - (void)dealloc
306 {
307 if (self->trust != NULL) {
308 CFRelease(self->trust);
309 self->trust = NULL;
310 }
311 }
312
313 sec_trust_t
314 sec_trust_create(SecTrustRef trust)
315 {
316 return [[SEC_CONCRETE_CLASS_NAME(sec_trust) alloc] initWithTrust:trust];
317 }
318
319 SecTrustRef
320 sec_trust_copy_ref(sec_trust_t object)
321 {
322 if (object == NULL) {
323 return SEC_NULL_BAD_INPUT;
324 }
325 if (object->trust != NULL) {
326 return __DECONST(SecTrustRef, CFRetain(object->trust));
327 }
328 return SEC_NULL_BAD_INPUT;
329 }
330
331 @end
332
333 SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_tls_extension,
334 {
335 uint16_t type;
336 sec_protocol_tls_ext_add_callback adder;
337 sec_protocol_tls_ext_parse_callback parser;
338 sec_protocol_tls_ext_free_callback freer;
339 });
340
341 @implementation SEC_CONCRETE_CLASS_NAME(sec_tls_extension)
342
343 - (instancetype)initWithCallbacks:(uint16_t)ext_type
344 adder:(sec_protocol_tls_ext_add_callback)add_block
345 parser:(sec_protocol_tls_ext_parse_callback)parse_block
346 freer:(sec_protocol_tls_ext_free_callback)free_block
347 {
348 if (add_block == nil) {
349 return SEC_NIL_BAD_INPUT;
350 }
351 if (parse_block == nil) {
352 return SEC_NIL_BAD_INPUT;
353 }
354 if (free_block == nil) {
355 return SEC_NIL_BAD_INPUT;
356 }
357
358 self = [super init];
359 if (self == nil) {
360 return SEC_NIL_OUT_OF_MEMORY;
361 }
362
363 self->type = ext_type;
364 self->adder = add_block;
365 self->parser = parse_block;
366 self->freer = free_block;
367 return self;
368 }
369
370 uint16_t
371 sec_tls_extension_get_type(sec_tls_extension_t extension)
372 {
373 if (extension == NULL) {
374 return 0;
375 }
376
377 return extension->type;
378 }
379
380 sec_protocol_tls_ext_add_callback
381 sec_tls_extension_copy_add_block(sec_tls_extension_t extension)
382 {
383 if (extension == NULL) {
384 return SEC_NULL_BAD_INPUT;
385 }
386
387 return extension->adder;
388 }
389
390 sec_protocol_tls_ext_parse_callback
391 sec_tls_extension_copy_parse_block(sec_tls_extension_t extension)
392 {
393 if (extension == NULL) {
394 return SEC_NULL_BAD_INPUT;
395 }
396
397 return extension->parser;
398 }
399
400 sec_protocol_tls_ext_free_callback
401 sec_tls_extension_copy_free_block(sec_tls_extension_t extension)
402 {
403 if (extension == NULL) {
404 return SEC_NULL_BAD_INPUT;
405 }
406
407 return extension->freer;
408 }
409
410 sec_tls_extension_t
411 sec_tls_extension_create(uint16_t type, sec_protocol_tls_ext_add_callback adder, sec_protocol_tls_ext_parse_callback parser, sec_protocol_tls_ext_free_callback freer)
412 {
413 return [[SEC_CONCRETE_CLASS_NAME(sec_tls_extension) alloc] initWithCallbacks:type adder:adder parser:parser freer:freer];
414 }
415
416 @end
417