]> git.saurik.com Git - apple/security.git/blame - libsecurity_transform/lib/TransformFactory.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_transform / lib / TransformFactory.cpp
CommitLineData
b1ab9ed8
A
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
11void 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
20CFMutableDictionaryRef TransformFactory::gRegistered;
21dispatch_once_t TransformFactory::gSetup;
22dispatch_queue_t TransformFactory::gRegisteredQueue;
23
24bool 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
41void 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
49void 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
56void TransformFactory::Setup()
57{
58 dispatch_once_f(&gSetup, NULL, Setup);
59}
60
61TransformFactory* 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
73SecTransformRef TransformFactory::MakeTransformWithType(CFStringRef type, CFErrorRef* baseError)
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[numberRegistered];
89 CFDictionaryGetKeysAndValues(gRegistered, (const void**)names, NULL);
90 for(int i = 0; i < numberRegistered; i++) {
91 if (i != 0) {
92 CFStringAppend(transformNames, CFSTR(", "));
93 }
94 CFStringAppend(transformNames, names[i]);
95 }
96
97 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered,
98 "The %s transform is not registered, choose from: %@", type,transformNames);
99
100 });
101#else
102 *baseError = CreateSecTransformErrorRef(kSecTransformTransformIsNotRegistered,
103 "The %s transform is not registered", type);
104#endif
105 }
106
107 return NULL;
108 }
109 else
110 {
111 return tf->Make();
112 }
113}
114
115
116
117TransformFactory::TransformFactory(CFStringRef type, bool registerGlobally, CFStringRef cftype) : mCFType(type)
118{
119 if (registerGlobally)
120 {
121 CoreFoundationObject::RegisterObject(cftype ? cftype : type, false);
122 }
123}