]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/SecCFWrappers.h
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / utilities / src / SecCFWrappers.h
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #ifndef _SECCFWRAPPERS_H_
26 #define _SECCFWRAPPERS_H_
27
28 #include <CoreFoundation/CFRuntime.h>
29 #include <CoreFoundation/CoreFoundation.h>
30
31 #include <utilities/SecCFRelease.h>
32 #include <utilities/debugging.h>
33 #include <utilities/SecCFError.h>
34
35 #include <IOKit/IOReturn.h>
36
37 #include <assert.h>
38 #include <dispatch/dispatch.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdio.h>
42
43 #include <corecrypto/ccdigest.h>
44
45 #if __has_feature(objc_arc)
46 #define __SECBRIDGE __bridge
47 #else
48 #define __SECBRIDGE
49 #endif
50
51 //
52 // Convenience routines.
53 //
54
55 //
56 // Macros for the pattern
57 //
58 // typedef struct _privateNewClass* NewClassRef;
59 //
60 // struct _privateNewClass {
61 // CFRuntimeBase _base;
62 // ... class additions
63 // };
64 //
65 // kClassNameRegisterClass
66 // kClassNameTypeID
67 //
68 // ClassNameGetTypeID()
69 //
70 // CFGiblisFor(NewClass);
71 //
72 // .. define NewClassDestroy
73 // .. define NewClassCopyDescription
74 //
75 // .. use CFTypeAllocate(NewClass, _privateNewClass, allocator);
76 //
77 //
78
79 // Call this to create a function that returns a singleton instance of type stype,
80 // which is initialized once by calling doThisOnce, with result in its context. Upon
81 // completion body should assign to *result.
82
83 extern CFStringRef kSecDebugFormatOption;
84
85 extern CFDictionaryRef SecGetDebugDescriptionFormatOptions(void);
86
87 typedef void (^SecBoolCFErrorCallback) (bool, CFErrorRef);
88
89 #define CFGiblisGetSingleton(returnType, giblisClassName, result, doThisOnce) \
90 returnType giblisClassName(void); \
91 returnType giblisClassName(void) { \
92 static dispatch_once_t s##giblisClassName##Once; \
93 static returnType s##giblisClassName##Singleton; \
94 returnType *result = &s##giblisClassName##Singleton; \
95 dispatch_once(&s##giblisClassName##Once, doThisOnce); \
96 return s##giblisClassName##Singleton; \
97 }
98
99 #define CFGiblisWithFunctions(gibliClassName, init_func, copy_func, finalize_func, equal_func, hash_func, copyFormattingDesc_func, copyDebugDesc_func, reclaim_func, refcount_func, run_once_block) \
100 CFGiblisGetSingleton(CFTypeID, gibliClassName##GetTypeID, typeID, (^{ \
101 void (^ const _onceBlock)(void) = (run_once_block); \
102 static const CFRuntimeClass s##gibliClassName##Class = { \
103 .version = (reclaim_func == NULL ? 0 : _kCFRuntimeResourcefulObject) \
104 | (refcount_func == NULL ? 0 : _kCFRuntimeCustomRefCount), \
105 .className = #gibliClassName, \
106 .init = init_func, \
107 .copy = copy_func, \
108 .finalize = finalize_func, \
109 .equal = equal_func, \
110 .hash = hash_func, \
111 .copyFormattingDesc = copyFormattingDesc_func, \
112 .copyDebugDesc = copyDebugDesc_func, \
113 .reclaim = reclaim_func, \
114 .refcount = refcount_func, \
115 }; \
116 *typeID = _CFRuntimeRegisterClass(&s##gibliClassName##Class); \
117 if (_onceBlock) \
118 _onceBlock(); \
119 }))
120
121 #define CFGiblisWithHashFor(gibliClassName) \
122 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
123 static void gibliClassName##Destroy(CFTypeRef cf); \
124 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
125 static CFHashCode gibliClassName##Hash(CFTypeRef cf); \
126 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
127 return gibliClassName##CopyFormatDescription(cf, SecGetDebugDescriptionFormatOptions());\
128 }\
129 \
130 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
131
132 #define CFGiblisWithCompareFor(gibliClassName) \
133 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
134 static void gibliClassName##Destroy(CFTypeRef cf); \
135 static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \
136 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
137 return gibliClassName##CopyFormatDescription(cf, SecGetDebugDescriptionFormatOptions());\
138 }\
139 \
140 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
141
142
143 #define CFGiblisFor(gibliClassName) \
144 static CFStringRef gibliClassName##CopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions); \
145 static void gibliClassName##Destroy(CFTypeRef cf); \
146 static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf){\
147 return gibliClassName##CopyFormatDescription(cf, SecGetDebugDescriptionFormatOptions());\
148 }\
149 \
150 CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, NULL, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL)
151
152 #define CFTypeAllocateWithSpace(classType, space, allocator) \
153 (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), space, NULL)
154
155 #define CFTypeAllocate(classType, internalType, allocator) \
156 CFTypeAllocateWithSpace(classType, sizeof(internalType) - sizeof(CFRuntimeBase), allocator)
157
158 #define SECWRAPPER_SENTINEL __attribute__((__sentinel__))
159
160 __BEGIN_DECLS
161
162 void withStringOfAbsoluteTime(CFAbsoluteTime at, void (^action)(CFStringRef decription));
163
164
165 //
166 // MARK: Call block function
167 //
168
169
170 static void apply_block_1(const void *value, void *context)
171 {
172 ((__SECBRIDGE void (^)(const void *value))context)(value);
173 }
174
175 static void apply_block_2(const void *key, const void *value, void *context)
176 {
177 ((__SECBRIDGE void (^)(const void *key, const void *value))context)(key, value);
178 }
179
180 //
181 // MARK: Type checking
182 //
183
184 static inline bool isArray(CFTypeRef cfType) {
185 return cfType && CFGetTypeID(cfType) == CFArrayGetTypeID();
186 }
187
188 static inline bool isSet(CFTypeRef cfType) {
189 return cfType && CFGetTypeID(cfType) == CFSetGetTypeID();
190 }
191
192 static inline bool isData(CFTypeRef cfType) {
193 return cfType && CFGetTypeID(cfType) == CFDataGetTypeID();
194 }
195
196 static inline bool isDate(CFTypeRef cfType) {
197 return cfType && CFGetTypeID(cfType) == CFDateGetTypeID();
198 }
199
200 static inline bool isDictionary(CFTypeRef cfType) {
201 return cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID();
202 }
203
204 static inline bool isNumber(CFTypeRef cfType) {
205 return cfType && CFGetTypeID(cfType) == CFNumberGetTypeID();
206 }
207
208 static inline bool isNumberOfType(CFTypeRef cfType, CFNumberType number) {
209 return isNumber(cfType) && CFNumberGetType((CFNumberRef)cfType) == number;
210 }
211
212 static inline bool isString(CFTypeRef cfType) {
213 return cfType && CFGetTypeID(cfType) == CFStringGetTypeID();
214 }
215
216 static inline bool isBoolean(CFTypeRef cfType) {
217 return cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID();
218 }
219
220 static inline bool isNull(CFTypeRef cfType) {
221 return cfType && CFGetTypeID(cfType) == CFNullGetTypeID();
222 }
223
224 //
225 // MARK CFEqual Helpers
226 //
227
228 static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right)
229 {
230 if (left == NULL || right == NULL)
231 return left == right;
232 else
233 return CFEqual(left, right);
234 }
235
236
237 //
238 // MARK: Printing
239 //
240
241 static void fprint_string(FILE *file, CFStringRef string) {
242 UInt8 buf[256];
243 CFRange range = { .location = 0 };
244 range.length = CFStringGetLength(string);
245 while (range.length > 0) {
246 CFIndex bytesUsed = 0;
247 CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed);
248 fwrite(buf, 1, bytesUsed, file);
249 range.length -= converted;
250 range.location += converted;
251 }
252 }
253
254 static inline void cffprint_v(FILE *file, CFStringRef fmt, va_list args) CF_FORMAT_FUNCTION(2, 0);
255 static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0);
256
257 static inline void cffprint_v(FILE *file, CFStringRef fmt, va_list args) {
258 CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args);
259 fprint_string(file, line);
260 CFRelease(line);
261 }
262
263 static inline void cffprint(FILE *file, CFStringRef fmt, ...) {
264 va_list args;
265 va_start(args, fmt);
266 cffprint_v(file, fmt, args);
267 va_end(args);
268 }
269
270 //
271 // MARK: CFError Helpers
272 //
273
274 /* Return false if possibleError is set. Propagates possibleError into *error
275 if *error is NULL, otherwise releases possibleError. */
276 static inline
277 bool CFErrorPropagate(CFErrorRef possibleError CF_CONSUMED, CFErrorRef *error) {
278 if (possibleError) {
279 if (error && !*error) {
280 *error = possibleError;
281 } else {
282 CFRelease(possibleError);
283 }
284 return false;
285 }
286 return true;
287 }
288
289 static inline bool CFErrorIsMalfunctioningKeybagError(CFErrorRef error){
290 switch(CFErrorGetCode(error))
291 {
292 case(kIOReturnError):
293 case(kIOReturnBusy):
294 case(kIOReturnNotPermitted):
295 break;
296 default:
297 return false;
298 }
299 return CFEqualSafe(CFErrorGetDomain(error), kSecKernDomain);
300 }
301
302 //
303 // MARK: CFNumber Helpers
304 //
305
306 static inline CFNumberRef CFNumberCreateWithCFIndex(CFAllocatorRef allocator, CFIndex value)
307 {
308 return CFNumberCreate(allocator, kCFNumberCFIndexType, &value);
309 }
310
311 //
312 // MARK: CFData Helpers
313 //
314
315 static inline CFMutableDataRef CFDataCreateMutableWithScratch(CFAllocatorRef allocator, CFIndex size) {
316 CFMutableDataRef result = CFDataCreateMutable(allocator, 0);
317 CFDataSetLength(result, size);
318
319 return result;
320 }
321
322 static inline void CFDataAppend(CFMutableDataRef appendTo, CFDataRef dataToAppend)
323 {
324 CFDataAppendBytes(appendTo, CFDataGetBytePtr(dataToAppend), CFDataGetLength(dataToAppend));
325 }
326
327 static inline CFDataRef CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range)
328 {
329 return CFDataCreateWithBytesNoCopy(allocator,
330 CFDataGetBytePtr(sourceData) + range.location, range.length,
331 kCFAllocatorNull);
332 }
333
334 static inline CFDataRef CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range)
335 {
336 return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length);
337 }
338
339 CFDataRef CFDataCreateWithRandomBytes(size_t len);
340
341 CFDataRef CFDataCreateWithInitializer(CFAllocatorRef allocator, CFIndex size, bool (^operation)(size_t size, uint8_t *buffer));
342
343 static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data, CFIndex extraLength)
344 {
345 CFIndex startOffset = CFDataGetLength(data);
346
347 CFDataIncreaseLength(data, extraLength);
348
349 return CFDataGetMutableBytePtr(data) + startOffset;
350 }
351
352 static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData)
353 {
354 return CFDataGetMutableBytePtr(theData) + CFDataGetLength(theData);
355 }
356
357 static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) {
358 return CFDataGetBytePtr(theData) + CFDataGetLength(theData);
359 }
360
361 static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right)
362 {
363 const size_t left_size = CFDataGetLength(left);
364 const size_t right_size = CFDataGetLength(right);
365 const size_t shortest = (left_size <= right_size) ? left_size : right_size;
366
367 int comparison = memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), shortest);
368
369 if (comparison > 0 || (comparison == 0 && left_size > right_size))
370 return kCFCompareGreaterThan;
371 else if (comparison < 0 || (comparison == 0 && left_size < right_size))
372 return kCFCompareLessThan;
373 else
374 return kCFCompareEqualTo;
375 }
376
377 static inline CFDataRef CFDataCreateWithHash(CFAllocatorRef allocator, const struct ccdigest_info *di, const uint8_t *buffer, const uint8_t length) {
378 CFMutableDataRef result = CFDataCreateMutableWithScratch(allocator, di->output_size);
379
380 ccdigest(di, length, buffer, CFDataGetMutableBytePtr(result));
381
382 return result;
383 }
384
385
386 static inline CFDataRef CFDataCreateCopyFromPositions(CFAllocatorRef allocator, CFDataRef source, CFIndex start, CFIndex end)
387 {
388 return CFDataCreateCopyFromRange(allocator, source, CFRangeMake(start, end - start));
389 }
390
391 static inline int nibletToByte(char niblet) {
392 if(niblet >= '0' && niblet <= '9') return niblet - '0';
393 if(niblet >= 'a' && niblet <= 'f') return niblet - 'a' + 10;
394 if(niblet >= 'A' && niblet <= 'F') return niblet - 'A' + 10;
395 return 0;
396 }
397
398 static inline CFDataRef CFDataCreateFromHexString(CFAllocatorRef allocator, CFStringRef sourceHex) {
399 CFIndex sourceLen = CFStringGetLength(sourceHex);
400 if((sourceLen % 2) != 0) return NULL;
401 const char *src = CFStringGetCStringPtr(sourceHex, kCFStringEncodingUTF8);
402 UInt8 bytes[sourceLen/2];
403 for(int i = 0; i < sourceLen; i+=2) {
404 bytes[i/2] = (UInt8) (nibletToByte(src[i]) * 16 + nibletToByte(src[i+1]));
405 }
406 return CFDataCreate(allocator, bytes, sourceLen/2);
407 }
408
409
410 //
411 // MARK: CFString Helpers
412 //
413
414 CFComparisonResult CFStringCompareSafe(const void *val1, const void *val2, void *context);
415
416 //
417 // Turn a CFString into an allocated UTF8-encoded C string.
418 //
419 static inline char *CFStringToCString(CFStringRef inStr)
420 {
421 if (!inStr)
422 return (char *)strdup("");
423 CFRetain(inStr); // compensate for release on exit
424
425 // need to extract into buffer
426 CFIndex length = CFStringGetLength(inStr); // in 16-bit character units
427 size_t len = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
428 char *buffer = (char *)malloc(len); // pessimistic
429 if (!CFStringGetCString(inStr, buffer, len, kCFStringEncodingUTF8))
430 buffer[0] = 0;
431
432 CFRelease(inStr);
433 return buffer;
434 }
435
436 // runs operation with inStr as a zero terminated C string
437 // in utf8 encoding passed to the operation block.
438 void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8Str));
439
440 // runs operation with inStr as a zero terminated C string
441 // in utf8 passed to the operation block, the length of
442 // the string is also provided to the block.
443 void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8Str, size_t utf8Length));
444
445 void CFStringPerformWithUTF8CFData(CFStringRef inStr, void (^operation)(CFDataRef stringAsData));
446
447 #include <CommonNumerics/CommonCRC.h>
448
449 static inline void CFStringAppendEncryptedData(CFMutableStringRef s, CFDataRef edata)
450 {
451 const uint8_t *bytes = CFDataGetBytePtr(edata);
452 CFIndex len = CFDataGetLength(edata);
453 CFStringAppendFormat(s, 0, CFSTR("%04lx:"), len);
454 if(len<=8) {
455 for (CFIndex ix = 0; ix < len; ++ix) {
456 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
457 }
458 } else {
459 uint64_t crc = 0;
460 CNCRC(kCN_CRC_64_ECMA_182, bytes+8, len-8, &crc);
461 for (CFIndex ix = 0; ix < 8; ++ix) {
462 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
463 }
464 CFStringAppendFormat(s, 0, CFSTR("...|%08llx"), crc);
465 }
466 }
467
468 static inline void CFStringAppendHexData(CFMutableStringRef s, CFDataRef data) {
469 const uint8_t *bytes = CFDataGetBytePtr(data);
470 CFIndex len = CFDataGetLength(data);
471 for (CFIndex ix = 0; ix < len; ++ix) {
472 CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]);
473 }
474 }
475
476 static inline CF_RETURNS_RETAINED CFStringRef CFDataCopyHexString(CFDataRef data) {
477 CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 2 * CFDataGetLength(data));
478 CFStringAppendHexData(hexString, data);
479 return hexString;
480 }
481
482 static inline void CFDataPerformWithHexString(CFDataRef data, void (^operation)(CFStringRef dataString)) {
483 CFStringRef hexString = data ? CFDataCopyHexString(data) : CFSTR("(null)");
484 operation(hexString);
485 CFRelease(hexString);
486 }
487
488 static inline void BufferPerformWithHexString(const UInt8 *bytes, CFIndex length, void (^operation)(CFStringRef dataString)) {
489 CFDataRef bufferAsData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorNull);
490
491 CFDataPerformWithHexString(bufferAsData, operation);
492
493 CFReleaseNull(bufferAsData);
494 }
495
496
497
498 static inline void CFStringWriteToFile(CFStringRef inStr, FILE* file)
499 {
500 CFStringPerformWithCStringAndLength(inStr, ^(const char *utf8Str, size_t utf8Length) {
501 fwrite(utf8Str, 1, utf8Length, file);
502 });
503 }
504
505 static inline void CFStringWriteToFileWithNewline(CFStringRef inStr, FILE* file)
506 {
507 CFStringWriteToFile(inStr, file);
508 fputc('\n', file);
509 }
510
511 static inline CFStringRef CFStringCreateTruncatedCopy(CFStringRef s, CFIndex len) {
512 if(!s) return NULL;
513 if(len >= CFStringGetLength(s)) return CFStringCreateCopy(kCFAllocatorDefault, s);
514 return CFStringCreateWithSubstring(kCFAllocatorDefault, s, CFRangeMake(0, len));
515 }
516
517 //
518 // MARK: CFCollectionHelpers
519 //
520
521 static inline
522 const void *SecCFRetainForCollection(CFAllocatorRef allocator, const void *value)
523 {
524 return CFRetain(value);
525 }
526
527 static inline
528 void SecCFReleaseForCollection(CFAllocatorRef allocator, const void *value)
529 {
530 CFRelease(value);
531 }
532
533 //
534 // MARK: CFArray Helpers
535 //
536
537 static inline CFIndex CFArrayRemoveAllValue(CFMutableArrayRef array, const void* value)
538 {
539 CFIndex position = kCFNotFound;
540 CFIndex numberRemoved = 0;
541
542 position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value);
543 while (position != kCFNotFound) {
544 CFArrayRemoveValueAtIndex(array, position);
545 ++numberRemoved;
546 position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value);
547 }
548
549 return numberRemoved;
550 }
551
552 static inline void CFArrayAppendAll(CFMutableArrayRef array, CFArrayRef arrayToAppend) {
553 CFArrayAppendArray(array, arrayToAppend, CFRangeMake(0, CFArrayGetCount(arrayToAppend)));
554 }
555
556 #define CFArrayForEachC(array, value) for (CFIndex _aCount = CFArrayGetCount(array), _aIX = 0;value = (__typeof__(value))(_aIX < _aCount ? CFArrayGetValueAtIndex(array, _aIX) : 0), _aIX < _aCount; ++_aIX)
557
558 static inline void CFArrayForEach(CFArrayRef array, void (^operation)(const void *value)) {
559 CFArrayApplyFunction(array, CFRangeMake(0, CFArrayGetCount(array)), apply_block_1, (__SECBRIDGE void *)operation);
560 }
561
562 static inline void CFArrayForEachReverse(CFArrayRef array, void (^operation)(const void *value)) {
563 for(CFIndex count = CFArrayGetCount(array); count > 0; --count) {
564 operation(CFArrayGetValueAtIndex(array, count - 1));
565 }
566 }
567
568 static inline const void *CFArrayGetValueMatching(CFArrayRef array, bool (^match)(const void *value)) {
569 CFIndex i, n = CFArrayGetCount(array);
570 for (i = 0; i < n; ++i) {
571 const void *value = CFArrayGetValueAtIndex(array, i);
572 if (match(value)) {
573 return value;
574 }
575 }
576 return NULL;
577 }
578
579 static inline bool CFArrayHasValueMatching(CFArrayRef array, bool (^match)(const void *value)) {
580 return CFArrayGetValueMatching(array, match) != NULL;
581 }
582
583 static inline void CFMutableArrayModifyValues(CFMutableArrayRef array, const void * (^process)(const void *value)) {
584 CFIndex i, n = CFArrayGetCount(array);
585 for (i = 0; i < n; ++i) {
586 const void *value = CFArrayGetValueAtIndex(array, i);
587 CFArraySetValueAtIndex(array, i, process(value));
588 }
589 }
590
591 static inline void CFArraySubtract(CFMutableArrayRef from, CFArrayRef remove) {
592 if (remove && from) {
593 CFArrayForEach(remove, ^(const void *value) {
594 CFArrayRemoveAllValue(from, value);
595 });
596 }
597 }
598
599 static inline CFMutableArrayRef CFArrayCreateDifference(CFAllocatorRef alloc, CFArrayRef set, CFArrayRef remove) {
600 CFMutableArrayRef result;
601 if (!set) {
602 result = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
603 } else {
604 result = CFArrayCreateMutableCopy(alloc, 0, set);
605 if (remove)
606 CFArraySubtract(result, remove);
607 }
608
609 return result;
610 }
611
612 //
613 // MARK: CFArray creation Var args helper functions.
614 //
615 static inline CFArrayRef CFArrayCreateCountedForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, CFIndex entries, va_list args)
616 {
617 const void *values[entries ? entries : 1];
618 for (CFIndex currentValue = 0; currentValue < entries; ++currentValue)
619 {
620 values[currentValue] = va_arg(args, void*);
621
622 if (values[currentValue] == NULL)
623 values[currentValue] = kCFNull;
624 }
625
626 return CFArrayCreate(allocator, values, entries, cbs);
627 }
628
629 static inline CFArrayRef CFArrayCreateForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, va_list args)
630 {
631 va_list count;
632 va_copy(count, args);
633
634 CFIndex entries = 0;
635 while (NULL != va_arg(count, void*)) {
636 entries += 1;
637 }
638
639 return CFArrayCreateCountedForVC(allocator, cbs, entries, args);
640
641 }
642
643
644
645 //
646 // MARK: CFArray of CFTypes support
647 //
648
649 static inline CFMutableArrayRef CFArrayCreateMutableForCFTypesWithCapacity(CFAllocatorRef allocator, CFIndex capacity)
650 {
651 return CFArrayCreateMutable(allocator, capacity, &kCFTypeArrayCallBacks);
652 }
653
654 static inline CFMutableArrayRef SECWRAPPER_SENTINEL CFArrayCreateMutableForCFTypesWith(CFAllocatorRef allocator, ...)
655 {
656
657 va_list args;
658 va_start(args, allocator);
659 CFIndex capacity = 0;
660 void* object = va_arg(args, void*);
661
662 while (object != NULL) {
663 object = va_arg(args, void*);
664 capacity++;
665 };
666
667 va_end(args);
668
669 CFMutableArrayRef result = CFArrayCreateMutableForCFTypesWithCapacity(allocator, capacity);
670
671 va_start(args, allocator);
672 object = va_arg(args, void*);
673
674 while (object != NULL) {
675 CFArrayAppendValue(result, object);
676 object = va_arg(args, void*);
677 };
678
679 va_end(args);
680 return result;
681 }
682
683
684 static inline CFMutableArrayRef CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator)
685 {
686 return CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
687 }
688
689 static inline CFArrayRef SECWRAPPER_SENTINEL CFArrayCreateForCFTypes(CFAllocatorRef allocator, ...)
690 {
691 va_list args;
692 va_start(args, allocator);
693 CFArrayRef allocatedArray = CFArrayCreateForVC(allocator, &kCFTypeArrayCallBacks, args);
694 va_end(args);
695 return allocatedArray;
696
697 }
698
699 static inline CFArrayRef CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...)
700 {
701 va_list args;
702 va_start(args, entries);
703 CFArrayRef allocatedArray = CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args);
704 va_end(args);
705 return allocatedArray;
706 }
707
708 static inline CFArrayRef CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args)
709 {
710 return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args);
711 }
712
713 //
714 // MARK: CFDictionary of CFTypes helpers
715 //
716
717 static void CFDictionarySetIfNonNull(CFMutableDictionaryRef dictionary, const void *key, const void *value) {
718 if (value) {
719 CFDictionarySetValue(dictionary, key, value);
720 }
721 }
722
723 static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args)
724 {
725 const void *keys[entries];
726 const void *values[entries];
727
728 for(CFIndex currentValue = 0; currentValue < entries; ++currentValue)
729 {
730 keys[currentValue] = va_arg(args, void*);
731 values[currentValue] = va_arg(args, void*);
732
733 if (values[currentValue] == NULL)
734 values[currentValue] = kCFNull;
735 }
736
737 return CFDictionaryCreate(allocator, keys, values, entries,
738 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
739 }
740
741 static inline CFDictionaryRef SECWRAPPER_SENTINEL CFDictionaryCreateForCFTypes(CFAllocatorRef allocator, ...)
742 {
743 va_list args;
744 va_start(args, allocator);
745
746 CFIndex entries = 0;
747 while (NULL != va_arg(args, void*)) {
748 entries += 2;
749 (void) va_arg(args, void*);
750 }
751
752 entries /= 2;
753 va_end(args);
754 va_start(args, allocator);
755 CFDictionaryRef allocatedDictionary = CFDictionaryCreateCountedForCFTypesV(allocator, entries, args);
756 va_end(args);
757 return allocatedDictionary;
758 }
759
760 static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...)
761 {
762 va_list args;
763 va_start(args, entries);
764 CFDictionaryRef allocatedDictionary = CFDictionaryCreateCountedForCFTypesV(allocator, entries, args);
765 va_end(args);
766
767 return allocatedDictionary;
768 }
769
770 static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator)
771 {
772 return CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
773 }
774
775 static inline CFMutableDictionaryRef SECWRAPPER_SENTINEL CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator, ...)
776 {
777 CFMutableDictionaryRef result = CFDictionaryCreateMutableForCFTypes(allocator);
778
779 va_list args;
780 va_start(args, allocator);
781
782 void* key = va_arg(args, void*);
783
784 while (key != NULL) {
785 CFDictionarySetValue(result, key, va_arg(args, void*));
786 key = va_arg(args, void*);
787 };
788 va_end(args);
789 return result;
790 }
791
792 static inline CFMutableDictionaryRef SECWRAPPER_SENTINEL CFDictionaryCreateMutableForCFTypesWithSafe(CFAllocatorRef allocator, ...)
793 {
794 CFMutableDictionaryRef result = CFDictionaryCreateMutableForCFTypes(allocator);
795
796 va_list args;
797 va_start(args, allocator);
798
799 void* key = va_arg(args, void*);
800
801 while (key != NULL) {
802 CFDictionarySetIfNonNull(result, key, va_arg(args, void*));
803 key = va_arg(args, void*);
804 };
805 va_end(args);
806 return result;
807 }
808
809 //
810 // MARK: CFSet Helpers
811 //
812
813 static inline CFMutableSetRef CFSetCreateMutableForCFTypes(CFAllocatorRef allocator)
814 {
815 return CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
816 }
817
818 static inline bool CFSetIsEmpty(CFSetRef set) {
819 return CFSetGetCount(set) == 0;
820 }
821
822 static inline void CFSetForEach(CFSetRef set, void (^operation)(const void *value)) {
823 CFSetApplyFunction(set, apply_block_1, (__SECBRIDGE void *)operation);
824 }
825
826 static inline void CFSetUnion(CFMutableSetRef set, CFSetRef unionWith) {
827 CFSetForEach(unionWith, ^(const void *value) {
828 CFSetSetValue(set, value);
829 });
830 }
831
832 static inline void CFSetSubtract(CFMutableSetRef set, CFSetRef subtract) {
833 CFSetForEach(subtract, ^(const void *value) {
834 CFSetRemoveValue(set, value);
835 });
836 }
837
838 static inline bool CFSetIsSubset(CFSetRef smaller, CFSetRef bigger) {
839 __block bool isSubset = true;
840 CFSetForEach(smaller, ^(const void *value) {
841 if (!CFSetContainsValue(bigger, value)) {
842 isSubset = false;
843 }
844 });
845
846 return isSubset;
847 }
848
849 static inline void CFSetSetValues(CFMutableSetRef set, CFArrayRef valuesToSet) {
850 CFArrayForEach(valuesToSet, ^(const void *value) {
851 CFSetSetValue(set, value);
852 });
853 }
854
855 static inline CFMutableArrayRef CFSetCopyValues(CFSetRef set) {
856 CFMutableArrayRef values = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
857
858 CFSetForEach(set, ^(const void *value) {
859 CFArrayAppendValue(values, value);
860 });
861
862 return values;
863 }
864
865 static inline bool CFSetIntersectionIsEmpty(CFSetRef set1, CFSetRef set2) {
866 __block bool intersectionIsEmpty = true;
867 CFSetForEach(set1, ^(const void *value) {
868 intersectionIsEmpty &= !CFSetContainsValue(set2, value);
869 });
870 return intersectionIsEmpty;
871 }
872
873 static inline bool CFSetIntersects(CFSetRef set1, CFSetRef set2) {
874 return !CFSetIntersectionIsEmpty(set1, set2);
875 }
876
877 static inline CFMutableSetRef CFSetCreateIntersection(CFAllocatorRef allocator, CFSetRef a, CFSetRef b) {
878 CFMutableSetRef result = CFSetCreateMutableCopy(allocator, 0, a);
879
880 CFSetRemoveAllValues(result);
881 CFSetForEach(a, ^(const void *value) {
882 if (CFSetContainsValue(b, value)) {
883 CFSetAddValue(result, value);
884 }
885 });
886
887 return result;
888 }
889
890 static inline CFSetRef CFSetCreateCopyOfArrayForCFTypes(CFArrayRef array) {
891 CFIndex count = CFArrayGetCount(array);
892 const void **values = (const void **)malloc(sizeof(const void *) * count);
893 CFArrayGetValues(array, CFRangeMake(0, count), values);
894 CFSetRef set = CFSetCreate(CFGetAllocator(array), values, count, &kCFTypeSetCallBacks);
895 free(values);
896 return set;
897 }
898
899 static inline void CFSetTransferObject(CFTypeRef object, CFMutableSetRef from, CFMutableSetRef to) {
900 CFSetAddValue(to, object);
901 CFSetRemoveValue(from, object);
902 }
903
904 //
905 // MARK: CFStringXxx Helpers
906 //
907
908 void CFStringArrayPerfromWithDelimeterWithDescription(CFArrayRef strings, CFStringRef start, CFStringRef end, void (^action)(CFStringRef description));
909 void CFStringArrayPerfromWithDescription(CFArrayRef strings, void (^action)(CFStringRef description));
910 void CFStringSetPerformWithDescription(CFSetRef set, void (^action)(CFStringRef description));
911
912 //
913 // MARK: CFDictionary Helpers
914 //
915
916 static inline void CFDictionaryForEach(CFDictionaryRef dictionary, void (^operation)(const void *key, const void *value)) {
917 CFDictionaryApplyFunction(dictionary, apply_block_2, (__SECBRIDGE void *)operation);
918 }
919
920 CFStringRef CFDictionaryCopyCompactDescription(CFDictionaryRef dictionary);
921 CFStringRef CFDictionaryCopySuperCompactDescription(CFDictionaryRef dictionary);
922
923 //
924 // MARK: CFCalendar helpers
925 //
926
927 void SecCFCalendarDoWithZuluCalendar(void(^action)(CFCalendarRef zuluCalendar));
928
929 //
930 // MARK: CFAbsoluteTime helpers
931 //
932
933 static inline CFAbsoluteTime CFAbsoluteTimeForCalendarMoment(CFCalendarRef cal, int year, int month, int day, int hour, int minute, int second) {
934 CFAbsoluteTime at;
935 CFCalendarComposeAbsoluteTime(cal, &at, "yMdHms", year, month, day, hour, minute, second);
936 return at;
937 }
938
939 static inline CFAbsoluteTime CFAbsoluteTimeForCalendarDay(CFCalendarRef cal, int year, int month, int day) {
940 CFAbsoluteTime at;
941 CFCalendarComposeAbsoluteTime(cal, &at, "yMd", year, month, day);
942 return at;
943 }
944
945 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianMoment(CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
946 {
947 CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar);
948 CFCalendarSetTimeZone(cal, tz);
949 CFAbsoluteTime at = CFAbsoluteTimeForCalendarMoment(cal, year, month, day, hour, minute, second);
950 CFReleaseSafe(cal);
951 return at;
952 }
953
954 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianDay(CFTimeZoneRef tz, int year, int month, int day)
955 {
956 CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar);
957 CFCalendarSetTimeZone(cal, tz);
958 CFAbsoluteTime at = CFAbsoluteTimeForCalendarDay(cal, year, month, day);
959 CFReleaseSafe(cal);
960 return at;
961 }
962
963 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluMoment(int year, int month, int day, int hour, int minute, int second)
964 {
965 __block CFAbsoluteTime result = 0.0;
966 SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) {
967 result = CFAbsoluteTimeForCalendarMoment(zuluCalendar, year, month, day, hour, minute, second);
968 });
969 return result;
970 }
971
972
973 static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluDay(int year, int month, int day)
974 {
975 __block CFAbsoluteTime result = 0.0;
976 SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) {
977 result = CFAbsoluteTimeForCalendarDay(zuluCalendar, year, month, day);
978 });
979 return result;
980 }
981
982
983
984 //
985 // MARK: CFDate Helpers
986 //
987
988 static inline CFDateRef CFDateCreateForGregorianMoment(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
989 {
990 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianMoment(tz, year, month, day, hour, minute, second));
991 }
992
993 static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second)
994 {
995 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianDay(tz, year, month, day));
996 }
997
998 static inline CFDateRef CFDateCreateForGregorianZuluMoment(CFAllocatorRef allocator, int year, int month, int day, int hour, int minute, int second)
999 {
1000 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluMoment(year, month, day, hour, minute, second));
1001 }
1002
1003 static inline CFDateRef CFDateCreateForGregorianZuluDay(CFAllocatorRef allocator, int year, int month, int day)
1004 {
1005 return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluDay(year, month, day));
1006 }
1007
1008 //
1009 // MARK: PropertyList Helpers
1010 //
1011
1012 //
1013 // Crazy reading and writing stuff
1014 //
1015
1016 static inline void CFPropertyListWriteToFile(CFPropertyListRef plist, CFURLRef file)
1017 {
1018 CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, file);
1019 CFErrorRef error = NULL;
1020
1021 CFWriteStreamOpen(writeStream);
1022 CFPropertyListWrite(plist, writeStream, kCFPropertyListBinaryFormat_v1_0, 0, &error);
1023 if (error)
1024 secerror("Can't write plist: %@", error);
1025
1026 CFReleaseNull(error);
1027 CFReleaseNull(writeStream);
1028 }
1029
1030 static inline CF_RETURNS_RETAINED CFPropertyListRef CFPropertyListReadFromFile(CFURLRef file)
1031 {
1032 CFPropertyListRef result = NULL;
1033 CFErrorRef error = NULL;
1034 CFBooleanRef isRegularFile;
1035 if (!CFURLCopyResourcePropertyForKey(file, kCFURLIsRegularFileKey, &isRegularFile, &error)) {
1036 secinfo("plist", "file %@: %@", file, error);
1037 } else if (CFBooleanGetValue(isRegularFile)) {
1038 CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, file);
1039 if (readStream) {
1040 if (CFReadStreamOpen(readStream)) {
1041 CFPropertyListFormat format;
1042 result = CFPropertyListCreateWithStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListMutableContainers, &format, &error);
1043 if (!result) {
1044 secerror("read plist from %@: %@", file, error);
1045 }
1046 }
1047 CFRelease(readStream);
1048 }
1049 }
1050 CFReleaseNull(error);
1051
1052 return result;
1053 }
1054
1055 __END_DECLS
1056
1057 #endif /* _SECCFWRAPPERS_H_ */