]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSManifest.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSManifest.c
1 /*
2 * Copyright (c) 2013-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 /*
26 * SOSManifest.c - Manifest object and some manipulation around it
27 */
28
29 #include <Security/SecureObjectSync/SOSManifest.h>
30 #include <Security/SecureObjectSync/SOSDigestVector.h>
31 #include <utilities/SecCFError.h>
32 #include <utilities/SecCFWrappers.h>
33 #include <utilities/SecCFCCWrappers.h>
34
35 CFStringRef kSOSManifestErrorDomain = CFSTR("com.apple.security.sos.manifest.error");
36
37 /* SOSManifest implementation. */
38 struct __OpaqueSOSManifest {
39 CFRuntimeBase _base;
40 CFDataRef digest;
41 CFDataRef digestVector;
42 struct SOSDigestVector dv;
43 };
44
45 CFGiblisWithCompareFor(SOSManifest)
46
47 static void SOSManifestDestroy(CFTypeRef cf) {
48 SOSManifestRef mf = (SOSManifestRef)cf;
49 CFReleaseSafe(mf->digest);
50 CFReleaseSafe(mf->digestVector);
51 }
52
53 static Boolean SOSManifestCompare(CFTypeRef cf1, CFTypeRef cf2) {
54 SOSManifestRef mf1 = (SOSManifestRef)cf1;
55 SOSManifestRef mf2 = (SOSManifestRef)cf2;
56 return CFEqualSafe(SOSManifestGetDigest(mf1, NULL), SOSManifestGetDigest(mf2, NULL));
57 }
58
59 SOSManifestRef SOSManifestCreateWithData(CFDataRef data, CFErrorRef *error)
60 {
61 SOSManifestRef manifest = CFTypeAllocate(SOSManifest, struct __OpaqueSOSManifest, kCFAllocatorDefault);
62 if (!manifest)
63 SecCFCreateErrorWithFormat(kSOSManifestCreateError, kSOSManifestErrorDomain, NULL, error, NULL, CFSTR("Failed to create manifest"));
64 else if (data)
65 manifest->digestVector = CFDataCreateCopy(kCFAllocatorDefault, data);
66 else
67 manifest->digestVector = CFDataCreate(kCFAllocatorDefault, NULL, 0);
68
69 assert(!manifest || manifest->digestVector != NULL);
70 return manifest;
71 }
72
73 SOSManifestRef SOSManifestCreateWithBytes(const uint8_t *bytes, size_t len,
74 CFErrorRef *error) {
75 CFDataRef data = CFDataCreate(kCFAllocatorDefault, bytes, (CFIndex)len);
76 SOSManifestRef manifest = SOSManifestCreateWithData(data, error);
77 CFReleaseSafe(data);
78 return manifest;
79 }
80
81 size_t SOSManifestGetSize(SOSManifestRef m) {
82 return m ? (size_t)CFDataGetLength(m->digestVector) : 0;
83 }
84
85 size_t SOSManifestGetCount(SOSManifestRef m) {
86 return m ? SOSManifestGetSize(m) / SOSDigestSize : 0;
87 }
88
89 const uint8_t *SOSManifestGetBytePtr(SOSManifestRef m) {
90 return m ? CFDataGetBytePtr(m->digestVector) : NULL;
91 }
92
93 CFDataRef SOSManifestGetData(SOSManifestRef m) {
94 return m ? m->digestVector : NULL;
95 }
96
97 const struct SOSDigestVector *SOSManifestGetDigestVector(SOSManifestRef manifest) {
98 if (!manifest) {
99 static struct SOSDigestVector nulldv = SOSDigestVectorInit;
100 return &nulldv;
101 }
102 manifest->dv.capacity = manifest->dv.count = SOSManifestGetCount(manifest);
103 manifest->dv.digest = (void *)SOSManifestGetBytePtr(manifest);
104 manifest->dv.unsorted = false;
105 return &manifest->dv;
106 }
107
108 bool SOSManifestDiff(SOSManifestRef a, SOSManifestRef b,
109 SOSManifestRef *a_minus_b, SOSManifestRef *b_minus_a,
110 CFErrorRef *error) {
111 bool result = true;
112 if (SOSManifestGetCount(a) == 0) {
113 //secnotice("manifest", "diff = b");
114 SOSManifestRef empty = SOSManifestCreateWithBytes(NULL, 0, error);
115 if (a_minus_b) *a_minus_b = empty;
116 if (b_minus_a) *b_minus_a = CFRetainSafe(b ? b : empty);
117 } else if (SOSManifestGetCount(b) == 0) {
118 //secnotice("manifest", "diff = a");
119 SOSManifestRef empty = SOSManifestCreateWithBytes(NULL, 0, error);
120 if (a_minus_b) *a_minus_b = CFRetainSafe(a ? a : empty);
121 if (b_minus_a) *b_minus_a = empty;
122 } else {
123 struct SOSDigestVector dvab = SOSDigestVectorInit, dvba = SOSDigestVectorInit;
124 SOSDigestVectorDiffSorted(SOSManifestGetDigestVector(a), SOSManifestGetDigestVector(b), &dvab, &dvba);
125 if (a_minus_b) {
126 *a_minus_b = SOSManifestCreateWithDigestVector(&dvab, error);
127 if (!*a_minus_b)
128 result = false;
129 }
130 if (b_minus_a) {
131 *b_minus_a = SOSManifestCreateWithDigestVector(&dvba, error);
132 if (!*b_minus_a)
133 result = false;
134 }
135 SOSDigestVectorFree(&dvab);
136 SOSDigestVectorFree(&dvba);
137 }
138 return result;
139 }
140
141
142 SOSManifestRef SOSManifestCreateWithDigestVector(struct SOSDigestVector *dv, CFErrorRef *error) {
143 if (!dv) return NULL;
144 if (dv->unsorted) SOSDigestVectorSort(dv);
145 return SOSManifestCreateWithBytes((const uint8_t *)dv->digest, dv->count * SOSDigestSize, error);
146 }
147
148 SOSManifestRef SOSManifestCreateWithPatch(SOSManifestRef base,
149 SOSManifestRef removals,
150 SOSManifestRef additions,
151 CFErrorRef *error) {
152 struct SOSDigestVector dvresult = SOSDigestVectorInit;
153 SOSManifestRef result;
154 if (SOSDigestVectorPatchSorted(SOSManifestGetDigestVector(base), SOSManifestGetDigestVector(removals),
155 SOSManifestGetDigestVector(additions), &dvresult, error)) {
156 result = SOSManifestCreateWithDigestVector(&dvresult, error);
157 } else {
158 result = NULL;
159 }
160 SOSDigestVectorFree(&dvresult);
161 return result;
162 }
163
164 // This is the set of elements in m2, but not in m1.
165 SOSManifestRef SOSManifestCreateComplement(SOSManifestRef m1,
166 SOSManifestRef m2,
167 CFErrorRef *error) {
168 // m2 \ emptySet => m2
169 if (SOSManifestGetCount(m1) == 0) {
170 //secnotice("manifest", "complement = m2");
171 return m2 ? CFRetainSafe(m2) : SOSManifestCreateWithBytes(NULL, 0, error);
172 }
173
174 struct SOSDigestVector dvresult = SOSDigestVectorInit;
175 SOSManifestRef result;
176 SOSDigestVectorComplementSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult);
177 result = SOSManifestCreateWithDigestVector(&dvresult, error);
178 SOSDigestVectorFree(&dvresult);
179 return result;
180 }
181
182 SOSManifestRef SOSManifestCreateIntersection(SOSManifestRef m1,
183 SOSManifestRef m2,
184 CFErrorRef *error) {
185 struct SOSDigestVector dvresult = SOSDigestVectorInit;
186 SOSManifestRef result;
187 SOSDigestVectorIntersectSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult);
188 result = SOSManifestCreateWithDigestVector(&dvresult, error);
189 SOSDigestVectorFree(&dvresult);
190 return result;
191 }
192
193 SOSManifestRef SOSManifestCreateUnion(SOSManifestRef m1,
194 SOSManifestRef m2,
195 CFErrorRef *error) {
196 if (SOSManifestGetCount(m1) == 0) {
197 //secnotice("manifest", "union = m2");
198 return m2 ? CFRetainSafe(m2) : SOSManifestCreateWithBytes(NULL, 0, error);
199 } else if (SOSManifestGetCount(m2) == 0) {
200 //secnotice("manifest", "union = m1");
201 return m1 ? CFRetainSafe(m1) : SOSManifestCreateWithBytes(NULL, 0, error);
202 } else {
203 struct SOSDigestVector dvresult = SOSDigestVectorInit;
204 SOSManifestRef result;
205 SOSDigestVectorUnionSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult);
206 result = SOSManifestCreateWithDigestVector(&dvresult, error);
207 SOSDigestVectorFree(&dvresult);
208 return result;
209 }
210 }
211
212 void SOSManifestForEach(SOSManifestRef m, void(^block)(CFDataRef e, bool *stop)) {
213 CFDataRef e;
214 const uint8_t *p, *q;
215 bool stop = false;
216 for (p = SOSManifestGetBytePtr(m), q = p + SOSManifestGetSize(m);
217 !stop && p + SOSDigestSize <= q; p += SOSDigestSize) {
218 e = CFDataCreateWithBytesNoCopy(0, p, SOSDigestSize, kCFAllocatorNull);
219 if (e) {
220 block(e, &stop);
221 CFRelease(e);
222 }
223 }
224 }
225
226 CFDataRef SOSManifestGetDigest(SOSManifestRef m, CFErrorRef *error) {
227 if (!m) return NULL;
228 if (!m->digest)
229 m->digest = CFDataCreateSHA1DigestWithBytes(kCFAllocatorDefault, SOSManifestGetSize(m), SOSManifestGetBytePtr(m), error);
230 return m->digest;
231 }
232
233 static CFStringRef SOSManifestCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
234 SOSManifestRef mf = (SOSManifestRef)cf;
235 CFMutableStringRef desc = CFStringCreateMutable(0, 0);
236 if (SOSManifestGetCount(mf) >= 8) {
237 const uint8_t *m = CFDataGetBytePtr(SOSManifestGetDigest(mf, NULL));
238 CFStringAppendFormat(desc, NULL, CFSTR("<[%zu:%02X%02X%02X%02X]"), SOSManifestGetCount(mf), m[0], m[1], m[2], m[3]);
239 } else {
240 CFStringAppendFormat(desc, NULL, CFSTR("<[%zu]"), SOSManifestGetCount(mf));
241 }
242 __block size_t maxEntries = 8;
243 SOSManifestForEach(mf, ^(CFDataRef e, bool *stop) {
244 const uint8_t *d = CFDataGetBytePtr(e);
245 CFStringAppendFormat(desc, NULL, CFSTR(" %02X%02X%02X%02X"), d[0], d[1], d[2], d[3]);
246 if (!--maxEntries) {
247 CFStringAppend(desc, CFSTR("..."));
248 *stop = true;
249 }
250 });
251 CFStringAppend(desc, CFSTR(">"));
252
253 return desc;
254 }