2  * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 #ifndef _SECCFWRAPPERS_H_ 
  26 #define _SECCFWRAPPERS_H_ 
  28 #include <CoreFoundation/CFRuntime.h> 
  29 #include <CoreFoundation/CoreFoundation.h> 
  31 #include <utilities/SecCFRelease.h> 
  32 #include <utilities/debugging.h> 
  33 #include <utilities/SecCFError.h> 
  35 #include <IOKit/IOReturn.h> 
  38 #include <dispatch/dispatch.h> 
  43 #include <corecrypto/ccdigest.h> 
  45 #if __has_feature(objc_arc) 
  46 #define __SECBRIDGE  __bridge 
  52 // Convenience routines. 
  56 // Macros for the pattern 
  58 // typedef struct _privateNewClass* NewClassRef; 
  60 // struct _privateNewClass { 
  61 //      CFRuntimeBase _base; 
  62 //      ... class additions 
  65 // kClassNameRegisterClass 
  68 // ClassNameGetTypeID() 
  70 // CFGiblisFor(NewClass); 
  72 // .. define NewClassDestroy 
  73 // .. define NewClassCopyDescription 
  75 // .. use CFTypeAllocate(NewClass, _privateNewClass, allocator); 
  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. 
  83 extern CFStringRef kSecDebugFormatOption
; 
  85 extern CFDictionaryRef 
SecGetDebugDescriptionFormatOptions(void); 
  87 typedef void (^SecBoolCFErrorCallback
) (bool, CFErrorRef
); 
  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; \ 
  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, \ 
 108         .finalize = finalize_func, \ 
 109         .equal = equal_func, \ 
 111         .copyFormattingDesc = copyFormattingDesc_func, \ 
 112         .copyDebugDesc = copyDebugDesc_func, \ 
 113         .reclaim = reclaim_func, \ 
 114         .refcount = refcount_func, \ 
 116     *typeID = _CFRuntimeRegisterClass(&s##gibliClassName##Class); \ 
 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());\ 
 130     CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL) 
 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());\ 
 140     CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL) 
 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());\ 
 150     CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, NULL, NULL, gibliClassName##CopyFormatDescription, gibliClassName##CopyDescription, NULL, NULL, NULL) 
 152 #define CFTypeAllocateWithSpace(classType, space, allocator) \ 
 153     (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), space, NULL) 
 155 #define CFTypeAllocate(classType, internalType, allocator) \ 
 156     CFTypeAllocateWithSpace(classType, sizeof(internalType) - sizeof(CFRuntimeBase), allocator) 
 158 #define SECWRAPPER_SENTINEL __attribute__((__sentinel__)) 
 162 void withStringOfAbsoluteTime(CFAbsoluteTime at
, void (^action
)(CFStringRef decription
)); 
 166 // MARK: Call block function 
 170 static void apply_block_1(const void *value
, void *context
) 
 172     ((__SECBRIDGE 
void (^)(const void *value
))context
)(value
); 
 175 static void apply_block_2(const void *key
, const void *value
, void *context
) 
 177     ((__SECBRIDGE 
void (^)(const void *key
, const void *value
))context
)(key
, value
); 
 181 // MARK: Type checking 
 184 static inline bool isArray(CFTypeRef cfType
) { 
 185     return cfType 
&& CFGetTypeID(cfType
) == CFArrayGetTypeID(); 
 188 static inline bool isSet(CFTypeRef cfType
) { 
 189     return cfType 
&& CFGetTypeID(cfType
) == CFSetGetTypeID(); 
 192 static inline bool isData(CFTypeRef cfType
) { 
 193     return cfType 
&& CFGetTypeID(cfType
) == CFDataGetTypeID(); 
 196 static inline bool isDate(CFTypeRef cfType
) { 
 197     return cfType 
&& CFGetTypeID(cfType
) == CFDateGetTypeID(); 
 200 static inline bool isDictionary(CFTypeRef cfType
) { 
 201     return cfType 
&& CFGetTypeID(cfType
) == CFDictionaryGetTypeID(); 
 204 static inline bool isNumber(CFTypeRef cfType
) { 
 205     return cfType 
&& CFGetTypeID(cfType
) == CFNumberGetTypeID(); 
 208 static inline bool isNumberOfType(CFTypeRef cfType
, CFNumberType number
) { 
 209     return isNumber(cfType
) && CFNumberGetType((CFNumberRef
)cfType
) == number
; 
 212 static inline bool isString(CFTypeRef cfType
) { 
 213     return cfType 
&& CFGetTypeID(cfType
) == CFStringGetTypeID(); 
 216 static inline bool isBoolean(CFTypeRef cfType
) { 
 217     return cfType 
&& CFGetTypeID(cfType
) == CFBooleanGetTypeID(); 
 220 static inline bool isNull(CFTypeRef cfType
) { 
 221     return cfType 
&& CFGetTypeID(cfType
) == CFNullGetTypeID(); 
 225 // MARK CFEqual Helpers 
 228 static inline bool CFEqualSafe(CFTypeRef left
, CFTypeRef right
) 
 230     if (left 
== NULL 
|| right 
== NULL
) 
 231         return left 
== right
; 
 233         return CFEqual(left
, right
); 
 241 static void fprint_string(FILE *file
, CFStringRef string
) { 
 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
; 
 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); 
 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
); 
 263 static inline void cffprint(FILE *file
, CFStringRef fmt
, ...) { 
 266     cffprint_v(file
, fmt
, args
); 
 271 // MARK: CFError Helpers 
 274 /* Return false if possibleError is set.  Propagates possibleError into *error 
 275    if *error is NULL, otherwise releases possibleError. */ 
 277 bool CFErrorPropagate(CFErrorRef possibleError CF_CONSUMED
, CFErrorRef 
*error
) { 
 279         if (error 
&& !*error
) { 
 280             *error 
= possibleError
; 
 282             CFRelease(possibleError
); 
 289 static inline bool CFErrorIsMalfunctioningKeybagError(CFErrorRef error
){ 
 290     switch(CFErrorGetCode(error
)) 
 292         case(kIOReturnError
): 
 294         case(kIOReturnNotPermitted
): 
 299     return CFEqualSafe(CFErrorGetDomain(error
), kSecKernDomain
); 
 303 // MARK: CFNumber Helpers 
 306 static inline CFNumberRef 
CFNumberCreateWithCFIndex(CFAllocatorRef allocator
, CFIndex value
) 
 308     return CFNumberCreate(allocator
, kCFNumberCFIndexType
, &value
); 
 312 // MARK: CFData Helpers 
 315 static inline CFMutableDataRef 
CFDataCreateMutableWithScratch(CFAllocatorRef allocator
, CFIndex size
) { 
 316     CFMutableDataRef result 
= CFDataCreateMutable(allocator
, 0); 
 317     CFDataSetLength(result
, size
); 
 322 static inline void CFDataAppend(CFMutableDataRef appendTo
, CFDataRef dataToAppend
) 
 324     CFDataAppendBytes(appendTo
, CFDataGetBytePtr(dataToAppend
), CFDataGetLength(dataToAppend
)); 
 327 static inline CFDataRef 
CFDataCreateReferenceFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
) 
 329     return CFDataCreateWithBytesNoCopy(allocator
, 
 330                                        CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
, 
 334 static inline CFDataRef 
CFDataCreateCopyFromRange(CFAllocatorRef allocator
, CFDataRef sourceData
, CFRange range
) 
 336     return CFDataCreate(allocator
, CFDataGetBytePtr(sourceData
) + range
.location
, range
.length
); 
 339 CFDataRef 
CFDataCreateWithRandomBytes(size_t len
); 
 341 CFDataRef 
CFDataCreateWithInitializer(CFAllocatorRef allocator
, CFIndex size
, bool (^operation
)(size_t size
, uint8_t *buffer
)); 
 343 static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data
, CFIndex extraLength
) 
 345     CFIndex startOffset 
= CFDataGetLength(data
); 
 347     CFDataIncreaseLength(data
, extraLength
); 
 349     return CFDataGetMutableBytePtr(data
) + startOffset
; 
 352 static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData
) 
 354     return CFDataGetMutableBytePtr(theData
) + CFDataGetLength(theData
); 
 357 static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData
) { 
 358     return CFDataGetBytePtr(theData
) + CFDataGetLength(theData
); 
 361 static inline CFComparisonResult 
CFDataCompare(CFDataRef left
, CFDataRef right
) 
 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
; 
 367     int comparison 
= memcmp(CFDataGetBytePtr(left
), CFDataGetBytePtr(right
), shortest
); 
 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
; 
 374         return kCFCompareEqualTo
; 
 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
); 
 380     ccdigest(di
, length
, buffer
, CFDataGetMutableBytePtr(result
)); 
 386 static inline CFDataRef 
CFDataCreateCopyFromPositions(CFAllocatorRef allocator
, CFDataRef source
, CFIndex start
, CFIndex end
) 
 388     return CFDataCreateCopyFromRange(allocator
, source
, CFRangeMake(start
, end 
- start
)); 
 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; 
 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])); 
 406     return CFDataCreate(allocator
, bytes
, sourceLen
/2); 
 411 // MARK: CFString Helpers 
 414 CFComparisonResult 
CFStringCompareSafe(const void *val1
, const void *val2
, void *context
); 
 417 // Turn a CFString into an allocated UTF8-encoded C string. 
 419 static inline char *CFStringToCString(CFStringRef inStr
) 
 422         return (char *)strdup(""); 
 423     CFRetain(inStr
);        // compensate for release on exit 
 425     // need to extract into buffer 
 426     CFIndex length 
= CFStringGetLength(inStr
);  // in 16-bit character units 
 427     size_t len 
= CFStringGetMaximumSizeForEncoding(length
, kCFStringEncodingUTF8
) + 1; 
 428     char *buffer 
= (char *)malloc(len
);                 // pessimistic 
 429     if (!CFStringGetCString(inStr
, buffer
, len
, kCFStringEncodingUTF8
)) 
 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
)); 
 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
)); 
 445 void CFStringPerformWithUTF8CFData(CFStringRef inStr
, void (^operation
)(CFDataRef stringAsData
)); 
 447 #include <CommonNumerics/CommonCRC.h> 
 449 static inline void CFStringAppendEncryptedData(CFMutableStringRef s
, CFDataRef edata
) 
 451     const uint8_t *bytes 
= CFDataGetBytePtr(edata
); 
 452     CFIndex len 
= CFDataGetLength(edata
); 
 453     CFStringAppendFormat(s
, 0, CFSTR("%04lx:"), len
); 
 455         for (CFIndex ix 
= 0; ix 
< len
; ++ix
) { 
 456             CFStringAppendFormat(s
, 0, CFSTR("%02X"), bytes
[ix
]); 
 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
]); 
 464         CFStringAppendFormat(s
, 0, CFSTR("...|%08llx"), crc
); 
 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
]); 
 476 static inline CF_RETURNS_RETAINED CFStringRef 
CFDataCopyHexString(CFDataRef data
) { 
 477     CFMutableStringRef hexString 
= CFStringCreateMutable(kCFAllocatorDefault
, 2 * CFDataGetLength(data
)); 
 478     CFStringAppendHexData(hexString
, data
); 
 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
); 
 488 static inline void BufferPerformWithHexString(const UInt8 
*bytes
, CFIndex length
, void (^operation
)(CFStringRef dataString
)) { 
 489     CFDataRef bufferAsData 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, bytes
, length
, kCFAllocatorNull
); 
 491     CFDataPerformWithHexString(bufferAsData
, operation
); 
 493     CFReleaseNull(bufferAsData
); 
 498 static inline void CFStringWriteToFile(CFStringRef inStr
, FILE* file
) 
 500     CFStringPerformWithCStringAndLength(inStr
, ^(const char *utf8Str
, size_t utf8Length
) { 
 501         fwrite(utf8Str
, 1, utf8Length
, file
); 
 505 static inline void CFStringWriteToFileWithNewline(CFStringRef inStr
, FILE* file
) 
 507     CFStringWriteToFile(inStr
, file
); 
 511 static inline CFStringRef 
CFStringCreateTruncatedCopy(CFStringRef s
, CFIndex len
) { 
 513     if(len 
>= CFStringGetLength(s
)) return CFStringCreateCopy(kCFAllocatorDefault
, s
); 
 514     return CFStringCreateWithSubstring(kCFAllocatorDefault
, s
, CFRangeMake(0, len
)); 
 518 // MARK: CFCollectionHelpers 
 522 const void *SecCFRetainForCollection(CFAllocatorRef allocator
, const void *value
) 
 524     return CFRetain(value
); 
 528 void SecCFReleaseForCollection(CFAllocatorRef allocator
, const void *value
) 
 534 // MARK: CFArray Helpers 
 537 static inline CFIndex 
CFArrayRemoveAllValue(CFMutableArrayRef array
, const void* value
) 
 539     CFIndex position 
= kCFNotFound
; 
 540     CFIndex numberRemoved 
= 0; 
 542     position 
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), value
); 
 543     while (position 
!= kCFNotFound
) { 
 544         CFArrayRemoveValueAtIndex(array
, position
); 
 546         position 
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), value
); 
 549     return numberRemoved
; 
 552 static inline void CFArrayAppendAll(CFMutableArrayRef array
, CFArrayRef arrayToAppend
) { 
 553     CFArrayAppendArray(array
, arrayToAppend
, CFRangeMake(0, CFArrayGetCount(arrayToAppend
))); 
 556 #define CFArrayForEachC(array, value) for (CFIndex _aCount = CFArrayGetCount(array), _aIX = 0;value = (__typeof__(value))(_aIX < _aCount ? CFArrayGetValueAtIndex(array, _aIX) : 0), _aIX < _aCount; ++_aIX) 
 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
); 
 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)); 
 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
); 
 579 static inline bool CFArrayHasValueMatching(CFArrayRef array
, bool (^match
)(const void *value
)) { 
 580     return CFArrayGetValueMatching(array
, match
) != NULL
; 
 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
)); 
 591 static inline void CFArraySubtract(CFMutableArrayRef from
, CFArrayRef remove
) { 
 592     if (remove 
&& from
) { 
 593         CFArrayForEach(remove
, ^(const void *value
) { 
 594             CFArrayRemoveAllValue(from
, value
); 
 599 static inline CFMutableArrayRef 
CFArrayCreateDifference(CFAllocatorRef alloc
, CFArrayRef set
, CFArrayRef remove
) { 
 600     CFMutableArrayRef result
; 
 602         result 
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
); 
 604         result 
= CFArrayCreateMutableCopy(alloc
, 0, set
); 
 606             CFArraySubtract(result
, remove
); 
 613 // MARK: CFArray creation Var args helper functions. 
 615 static inline CFArrayRef 
CFArrayCreateCountedForVC(CFAllocatorRef allocator
, const CFArrayCallBacks 
*cbs
, CFIndex entries
, va_list args
) 
 617     CFMutableArrayRef array 
= CFArrayCreateMutable(allocator
, entries
, cbs
); 
 621     for (CFIndex currentValue 
= 0; currentValue 
< entries
; ++currentValue
) { 
 622         const void * value 
= va_arg(args
, const void *); 
 626         CFArrayAppendValue(array
, value
); 
 629     CFArrayRef constArray 
= CFArrayCreateCopy(allocator
, array
); 
 634 static inline CFArrayRef 
CFArrayCreateForVC(CFAllocatorRef allocator
, const CFArrayCallBacks 
*cbs
, va_list args
) 
 637     va_copy(count
, args
); 
 640     while (NULL 
!= va_arg(count
, void*)) { 
 644     return CFArrayCreateCountedForVC(allocator
, cbs
, entries
, args
); 
 650 // MARK: CFArray of CFTypes support 
 653 static inline CFMutableArrayRef 
CFArrayCreateMutableForCFTypesWithCapacity(CFAllocatorRef allocator
, CFIndex capacity
) 
 655     return CFArrayCreateMutable(allocator
, capacity
, &kCFTypeArrayCallBacks
); 
 658 static inline CFMutableArrayRef SECWRAPPER_SENTINEL 
CFArrayCreateMutableForCFTypesWith(CFAllocatorRef allocator
, ...) 
 662     va_start(args
, allocator
); 
 663     CFIndex capacity 
= 0; 
 664     void* object 
= va_arg(args
, void*); 
 666     while (object 
!= NULL
) { 
 667         object 
= va_arg(args
, void*); 
 673     CFMutableArrayRef result 
= CFArrayCreateMutableForCFTypesWithCapacity(allocator
, capacity
); 
 675     va_start(args
, allocator
); 
 676     object 
= va_arg(args
, void*); 
 678     while (object 
!= NULL
) { 
 679         CFArrayAppendValue(result
, object
); 
 680         object 
= va_arg(args
, void*); 
 688 static inline CFMutableArrayRef 
CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator
) 
 690     return CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
); 
 693 static inline CFArrayRef SECWRAPPER_SENTINEL 
CFArrayCreateForCFTypes(CFAllocatorRef allocator
, ...) 
 696     va_start(args
, allocator
); 
 697     CFArrayRef allocatedArray 
= CFArrayCreateForVC(allocator
, &kCFTypeArrayCallBacks
, args
); 
 699     return allocatedArray
; 
 703 static inline CFArrayRef 
CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator
, CFIndex entries
, ...) 
 706     va_start(args
, entries
); 
 707     CFArrayRef allocatedArray 
= CFArrayCreateCountedForVC(allocator
, &kCFTypeArrayCallBacks
, entries
, args
); 
 709     return allocatedArray
; 
 712 static inline CFArrayRef 
CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator
, CFIndex entries
, va_list args
) 
 714     return CFArrayCreateCountedForVC(allocator
, &kCFTypeArrayCallBacks
, entries
, args
); 
 718 // MARK: CFDictionary of CFTypes helpers 
 721 static void CFDictionarySetIfNonNull(CFMutableDictionaryRef dictionary
, const void *key
, const void *value
) { 
 723         CFDictionarySetValue(dictionary
, key
, value
); 
 727 static inline CFDictionaryRef 
CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator
, CFIndex entries
, va_list args
) 
 729     CFMutableDictionaryRef dictionary 
= CFDictionaryCreateMutable(allocator
, entries
, 
 730                                                                   &kCFTypeDictionaryKeyCallBacks
, 
 731                                                                   &kCFTypeDictionaryValueCallBacks
); 
 732     if (dictionary 
== NULL
) { 
 736     for(CFIndex currentValue 
= 0; currentValue 
< entries
; ++currentValue
) { 
 737         CFTypeRef key 
= va_arg(args
, CFTypeRef
); 
 738         CFTypeRef value 
= va_arg(args
, CFTypeRef
); 
 742         CFDictionarySetValue(dictionary
, key
, value
); 
 745     CFDictionaryRef constDictionary 
= CFDictionaryCreateCopy(allocator
, dictionary
); 
 746     CFRelease(dictionary
); 
 747     return constDictionary
; 
 750 static inline CFDictionaryRef SECWRAPPER_SENTINEL 
CFDictionaryCreateForCFTypes(CFAllocatorRef allocator
, ...) 
 753     va_start(args
, allocator
); 
 756     while (NULL 
!= va_arg(args
, void*)) { 
 758         (void) va_arg(args
, void*); 
 763     va_start(args
, allocator
); 
 764     CFDictionaryRef allocatedDictionary 
= CFDictionaryCreateCountedForCFTypesV(allocator
, entries
, args
); 
 766     return allocatedDictionary
; 
 769 static inline CFDictionaryRef 
CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator
, CFIndex entries
, ...) 
 772     va_start(args
, entries
); 
 773     CFDictionaryRef allocatedDictionary 
= CFDictionaryCreateCountedForCFTypesV(allocator
, entries
, args
); 
 776     return allocatedDictionary
; 
 779 static inline CFMutableDictionaryRef 
CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator
) 
 781     return CFDictionaryCreateMutable(allocator
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 784 static inline CFMutableDictionaryRef SECWRAPPER_SENTINEL 
CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator
, ...) 
 786     CFMutableDictionaryRef result 
= CFDictionaryCreateMutableForCFTypes(allocator
); 
 789     va_start(args
, allocator
); 
 791     void* key 
= va_arg(args
, void*); 
 793     while (key 
!= NULL
) { 
 794         CFDictionarySetValue(result
, key
, va_arg(args
, void*)); 
 795         key 
= va_arg(args
, void*); 
 801 static inline CFMutableDictionaryRef SECWRAPPER_SENTINEL 
CFDictionaryCreateMutableForCFTypesWithSafe(CFAllocatorRef allocator
, ...) 
 803     CFMutableDictionaryRef result 
= CFDictionaryCreateMutableForCFTypes(allocator
); 
 806     va_start(args
, allocator
); 
 808     void* key 
= va_arg(args
, void*); 
 810     while (key 
!= NULL
) { 
 811         CFDictionarySetIfNonNull(result
, key
, va_arg(args
, void*)); 
 812         key 
= va_arg(args
, void*); 
 819 // MARK: CFSet Helpers 
 822 static inline CFMutableSetRef 
CFSetCreateMutableForCFTypes(CFAllocatorRef allocator
) 
 824     return CFSetCreateMutable(allocator
, 0, &kCFTypeSetCallBacks
); 
 827 static inline bool CFSetIsEmpty(CFSetRef set
) { 
 828     return CFSetGetCount(set
) == 0; 
 831 static inline void CFSetForEach(CFSetRef set
, void (^operation
)(const void *value
)) { 
 832     CFSetApplyFunction(set
, apply_block_1
, (__SECBRIDGE 
void *)operation
); 
 835 static inline void CFSetUnion(CFMutableSetRef set
, CFSetRef unionWith
) { 
 836     CFSetForEach(unionWith
, ^(const void *value
) { 
 837         CFSetSetValue(set
, value
); 
 841 static inline void CFSetSubtract(CFMutableSetRef set
, CFSetRef subtract
) { 
 842     CFSetForEach(subtract
, ^(const void *value
) { 
 843         CFSetRemoveValue(set
, value
); 
 847 static inline bool CFSetIsSubset(CFSetRef smaller
, CFSetRef bigger
) { 
 848     __block 
bool isSubset 
= true; 
 849     CFSetForEach(smaller
, ^(const void *value
) { 
 850         if (!CFSetContainsValue(bigger
, value
)) { 
 858 static inline void CFSetSetValues(CFMutableSetRef set
, CFArrayRef valuesToSet
) { 
 859     CFArrayForEach(valuesToSet
, ^(const void *value
) { 
 860         CFSetSetValue(set
, value
); 
 864 static inline CFMutableArrayRef 
CFSetCopyValues(CFSetRef set
) { 
 865     CFMutableArrayRef values 
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
); 
 867     CFSetForEach(set
, ^(const void *value
) { 
 868         CFArrayAppendValue(values
, value
); 
 874 static inline bool CFSetIntersectionIsEmpty(CFSetRef set1
, CFSetRef set2
) { 
 875     __block 
bool intersectionIsEmpty 
= true; 
 876     CFSetForEach(set1
, ^(const void *value
) { 
 877         intersectionIsEmpty 
&= !CFSetContainsValue(set2
, value
); 
 879     return intersectionIsEmpty
; 
 882 static inline bool CFSetIntersects(CFSetRef set1
, CFSetRef set2
) { 
 883     return !CFSetIntersectionIsEmpty(set1
, set2
); 
 886 static inline CFMutableSetRef 
CFSetCreateIntersection(CFAllocatorRef allocator
, CFSetRef a
, CFSetRef b
) { 
 887     CFMutableSetRef result 
= CFSetCreateMutableCopy(allocator
, 0, a
); 
 889     CFSetRemoveAllValues(result
); 
 890     CFSetForEach(a
, ^(const void *value
) { 
 891         if (CFSetContainsValue(b
, value
)) { 
 892             CFSetAddValue(result
, value
); 
 899 static inline CFSetRef 
CFSetCreateCopyOfArrayForCFTypes(CFArrayRef array
) { 
 900     CFIndex count 
= CFArrayGetCount(array
); 
 901     const void **values 
= (const void **)malloc(sizeof(const void *) * count
); 
 902     CFArrayGetValues(array
, CFRangeMake(0, count
), values
); 
 903     CFSetRef set 
= CFSetCreate(CFGetAllocator(array
), values
, count
, &kCFTypeSetCallBacks
); 
 908 static inline void CFSetTransferObject(CFTypeRef object
, CFMutableSetRef from
, CFMutableSetRef to
) { 
 909     CFSetAddValue(to
, object
); 
 910     CFSetRemoveValue(from
, object
); 
 914 // MARK: CFStringXxx Helpers 
 917 void CFStringArrayPerformWithDelimiterWithDescription(CFArrayRef strings
, CFStringRef start
, CFStringRef end
, void (^action
)(CFStringRef description
)); 
 918 void CFStringArrayPerformWithDescription(CFArrayRef strings
, void (^action
)(CFStringRef description
)); 
 919 void CFStringSetPerformWithDescription(CFSetRef set
, void (^action
)(CFStringRef description
)); 
 922 // MARK: CFDictionary Helpers 
 925 static inline void CFDictionaryForEach(CFDictionaryRef dictionary
, void (^operation
)(const void *key
, const void *value
)) { 
 926     CFDictionaryApplyFunction(dictionary
, apply_block_2
, (__SECBRIDGE 
void *)operation
); 
 929 CFStringRef 
CFDictionaryCopyCompactDescription(CFDictionaryRef dictionary
); 
 930 CFStringRef 
CFDictionaryCopySuperCompactDescription(CFDictionaryRef dictionary
); 
 933 // MARK: CFCalendar helpers 
 936 void SecCFCalendarDoWithZuluCalendar(void(^action
)(CFCalendarRef zuluCalendar
)); 
 939 // MARK: CFAbsoluteTime helpers 
 942 static inline CFAbsoluteTime 
CFAbsoluteTimeForCalendarMoment(CFCalendarRef cal
, int year
, int month
, int day
, int hour
, int minute
, int second
) { 
 944     CFCalendarComposeAbsoluteTime(cal
, &at
, "yMdHms", year
, month
, day
, hour
, minute
, second
); 
 948 static inline CFAbsoluteTime 
CFAbsoluteTimeForCalendarDay(CFCalendarRef cal
, int year
, int month
, int day
) { 
 950     CFCalendarComposeAbsoluteTime(cal
, &at
, "yMd", year
, month
, day
); 
 954 static inline CFAbsoluteTime 
CFAbsoluteTimeForGregorianMoment(CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
) 
 956     CFCalendarRef cal 
= CFCalendarCreateWithIdentifier(NULL
, kCFGregorianCalendar
); 
 957     CFCalendarSetTimeZone(cal
, tz
); 
 958     CFAbsoluteTime at 
= CFAbsoluteTimeForCalendarMoment(cal
, year
, month
, day
, hour
, minute
, second
); 
 963 static inline CFAbsoluteTime 
CFAbsoluteTimeForGregorianDay(CFTimeZoneRef tz
, int year
, int month
, int day
) 
 965     CFCalendarRef cal 
= CFCalendarCreateWithIdentifier(NULL
, kCFGregorianCalendar
); 
 966     CFCalendarSetTimeZone(cal
, tz
); 
 967     CFAbsoluteTime at 
= CFAbsoluteTimeForCalendarDay(cal
, year
, month
, day
); 
 972 static inline CFAbsoluteTime 
CFAbsoluteTimeForGregorianZuluMoment(int year
, int month
, int day
, int hour
, int minute
, int second
) 
 974     __block CFAbsoluteTime result 
= 0.0; 
 975     SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar
) { 
 976         result 
= CFAbsoluteTimeForCalendarMoment(zuluCalendar
, year
, month
, day
, hour
, minute
, second
); 
 982 static inline CFAbsoluteTime 
CFAbsoluteTimeForGregorianZuluDay(int year
, int month
, int day
) 
 984     __block CFAbsoluteTime result 
= 0.0; 
 985     SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar
) { 
 986         result 
= CFAbsoluteTimeForCalendarDay(zuluCalendar
, year
, month
, day
); 
 994 // MARK: CFDate Helpers 
 997 static inline CFDateRef 
CFDateCreateForGregorianMoment(CFAllocatorRef allocator
, CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
) 
 999     return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianMoment(tz
, year
, month
, day
, hour
, minute
, second
)); 
1002 static inline CFDateRef 
CFDateCreateForGregorianDay(CFAllocatorRef allocator
, CFTimeZoneRef tz
, int year
, int month
, int day
, int hour
, int minute
, int second
) 
1004     return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianDay(tz
, year
, month
, day
)); 
1007 static inline CFDateRef 
CFDateCreateForGregorianZuluMoment(CFAllocatorRef allocator
, int year
, int month
, int day
, int hour
, int minute
, int second
) 
1009     return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianZuluMoment(year
, month
, day
, hour
, minute
, second
)); 
1012 static inline CFDateRef 
CFDateCreateForGregorianZuluDay(CFAllocatorRef allocator
, int year
, int month
, int day
) 
1014     return CFDateCreate(allocator
, CFAbsoluteTimeForGregorianZuluDay(year
, month
, day
)); 
1018 // MARK: PropertyList Helpers 
1022 // Crazy reading and writing stuff 
1025 static inline void CFPropertyListWriteToFile(CFPropertyListRef plist
, CFURLRef file
) 
1027     CFWriteStreamRef writeStream 
= CFWriteStreamCreateWithFile(kCFAllocatorDefault
, file
); 
1028     CFErrorRef error 
= NULL
; 
1030     CFWriteStreamOpen(writeStream
); 
1031     CFPropertyListWrite(plist
, writeStream
, kCFPropertyListBinaryFormat_v1_0
, 0, &error
); 
1033         secerror("Can't write plist: %@", error
); 
1035     CFReleaseNull(error
); 
1036     CFReleaseNull(writeStream
); 
1039 static inline CF_RETURNS_RETAINED CFPropertyListRef 
CFPropertyListReadFromFile(CFURLRef file
) 
1041     CFPropertyListRef result 
= NULL
; 
1042     CFErrorRef error 
= NULL
; 
1043     CFBooleanRef isRegularFile
; 
1044     if (!CFURLCopyResourcePropertyForKey(file
, kCFURLIsRegularFileKey
, &isRegularFile
, &error
)) { 
1045         secinfo("plist", "file %@: %@", file
, error
); 
1046     } else if (CFBooleanGetValue(isRegularFile
)) { 
1047         CFReadStreamRef readStream 
= CFReadStreamCreateWithFile(kCFAllocatorDefault
, file
); 
1049             if (CFReadStreamOpen(readStream
)) { 
1050                 CFPropertyListFormat format
; 
1051                 result 
= CFPropertyListCreateWithStream(kCFAllocatorDefault
, readStream
, 0, kCFPropertyListMutableContainers
, &format
, &error
); 
1053                     secerror("read plist from %@: %@", file
, error
); 
1056             CFRelease(readStream
); 
1059     CFReleaseNull(error
); 
1066 #endif /* _SECCFWRAPPERS_H_ */