TransformFactory.cpp
1 #include <libkern/OSAtomic.h> 2 3 #include "TransformFactory.h" 4 #include "NullTransform.h" 5 #include "Digest.h" 6 #include "EncryptTransform.h" 7 #include "GroupTransform.h" 8 #include "Utilities.h" 9 10 11 void TransformFactory::RegisterTransforms() 12 { 13 RegisterTransform_prelocked(NullTransform::MakeTransformFactory(), NULL); 14 RegisterTransform_prelocked(DigestTransform::MakeTransformFactory(), NULL); 15 RegisterTransform_prelocked(EncryptTransform::MakeTransformFactory(), NULL); 16 RegisterTransform_prelocked(DecryptTransform::MakeTransformFactory(), NULL); 17 RegisterTransform_prelocked(GroupTransform::MakeTransformFactory(), NULL); 18 } 19 20 CFMutableDictionaryRef TransformFactory::gRegistered; 21 dispatch_once_t TransformFactory::gSetup; 22 dispatch_queue_t TransformFactory::gRegisteredQueue; 23 24 bool TransformFactory::RegisterTransform_prelocked(TransformFactory* tf, CFStringRef cfname) 25 { 26 if (!CFDictionaryContainsKey(gRegistered, tf->mCFType)) { 27 CFDictionaryAddValue(gRegistered, tf->mCFType, tf); 28 if (!cfname) { 29 CoreFoundationObject::RegisterObject(tf->mCFType, false); 30 } else { 31 if (!CoreFoundationObject::FindObjectType(cfname)) { 32 CoreFoundationObject::RegisterObject(cfname, false); 33 } 34 } 35 } 36 37 return true; 38 } 39 40 41 void TransformFactory::RegisterTransform(TransformFactory* tf, CFStringRef cfname) 42 { 43 dispatch_once_f(&gSetup, NULL, Setup); 44 dispatch_barrier_sync(gRegisteredQueue, ^{ 45 RegisterTransform_prelocked(tf, cfname); 46 }); 47 } 48 49 void TransformFactory::Setup(void *) 50 { 51 gRegisteredQueue = dispatch_queue_create("com.apple.security.TransformFactory.Registered", DISPATCH_QUEUE_CONCURRENT); 52 gRegistered = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL); 53 RegisterTransforms(); 54 } 55 56 void TransformFactory::Setup() 57 { 58 dispatch_once_f(&gSetup, NULL, Setup); 59 } 60 61 TransformFactory* TransformFactory::FindTransformFactoryByType(CFStringRef name) 62 { 63 dispatch_once_f(&gSetup, NULL, Setup); 64 __block TransformFactory *ret; 65 dispatch_barrier_sync(gRegisteredQueue, ^{ 66 ret = (TransformFactory*)CFDictionaryGetValue(gRegistered, name); 67 }); 68 return ret; 69 } 70 71 72 73 SecTransformRef TransformFactory::MakeTransformWithType(CFStringRef type, CFErrorRef* baseError) CF_RETURNS_RETAINED 74 { 75 TransformFactory* tf = FindTransformFactoryByType(type); 76 if (!tf) 77 { 78 if (baseError != NULL) 79 { 80 #if 0 81 // This version lists out all regestered transform types. 82 // It is useful more for debugging then for anything else, 83 // so it is great to keep around, but normally not so good 84 // to run. 85 dispatch_barrier_sync(gRegisteredQueue, ^(void) { 86 CFMutableStringRef transformNames = CFStringCreateMutable(NULL, 0); 87 CFIndex numberRegistered = CFDictionaryGetCount(gRegistered); 88 CFStringRef *names = (CFStringRef*)malloc(numberRegistered * sizeof(CFStringRef)); 89 if (names == NULL) { 90 *baseError = CreateSecTransformErrorRef(errSecMemoryError, 91 "The %s transform names can't be allocated.", type); 92 return NULL; 93 } 94 95 CFDictionaryGetKeysAndValues(gRegistered, (const void**)names, NULL); 96 for(int i = 0; i < numberRegistered; i++) { 97 if (i != 0) { 98 CFStringAppend(transformNames, CFSTR(", ")); 99 } 100 CFStringAppend(transformNames, names[i]); 101 } 102 103 free(names); 104 105 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, 106 "The %s transform is not registered, choose from: %@", type,transformNames); 107 108 }); 109 #else 110 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered, 111 "The %s transform is not registered", type); 112 #endif 113 } 114 115 return NULL; 116 } 117 else 118 { 119 return tf->Make(); 120 } 121 } 122 123 124 125 TransformFactory::TransformFactory(CFStringRef type, bool registerGlobally, CFStringRef cftype) : mCFType(type) 126 { 127 if (registerGlobally) 128 { 129 CoreFoundationObject::RegisterObject(cftype ? cftype : type, false); 130 } 131 }