2 * Copyright (c) 2015 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 #include <Security/SecureObjectSync/SOSManifest.h>
26 #include <Security/SecureObjectSync/SOSMessage.h>
28 #include "secd_regressions.h"
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/SecCFRelease.h>
32 #include <utilities/der_plist.h>
33 #include <Security/SecureObjectSync/SOSDigestVector.h>
34 #include <securityd/SecDbItem.h>
37 static int kTestTestCount
= 68;
40 #define okmfcomplement(r, b, n, ...) test_okmfcomplement(r, b, n, test_create_description(__VA_ARGS__), test_directive, test_reason, __FILE__, __LINE__, NULL)
41 #define okmfdiff(a, b, eab,eba, ...) test_okmfdiff(a, b, eab, eba, test_create_description(__VA_ARGS__), test_directive, test_reason, __FILE__, __LINE__, NULL)
42 #define okmfintersection(a, b, n, ...) test_okmfintersection(a, b, n, test_create_description(__VA_ARGS__), test_directive, test_reason, __FILE__, __LINE__, NULL)
43 #define okmfpatch(b, r, a, n, ...) test_okmfpatch(b, r, a, n, test_create_description(__VA_ARGS__), test_directive, test_reason, __FILE__, __LINE__, NULL)
44 #define okmfunion(a, b, n, ...) test_okmfunion(a, b, n, test_create_description(__VA_ARGS__), test_directive, test_reason, __FILE__, __LINE__, NULL)
46 static void appendManifestDescription(CFMutableStringRef string
, CFStringRef prefix
, SOSManifestRef mf
) {
48 CFStringAppend(string
, prefix
);
50 CFStringAppend(string
, CFSTR("null"));
51 } else if (SOSManifestGetCount(mf
) == 0) {
52 CFStringAppend(string
, CFSTR("empty"));
55 const uint8_t *d
= SOSManifestGetBytePtr(mf
);
56 for (CFIndex endIX
= SOSManifestGetCount(mf
), curIX
= 0; curIX
< endIX
; ++curIX
, d
+= SOSDigestSize
) {
57 CFStringAppendFormat(string
, NULL
, CFSTR("%c%c"), prefix
, *d
);
60 CFStringAppend(string
, CFSTR("}"));
64 static int appendManifestComparison(CFMutableStringRef string
, CFStringRef prefix
, SOSManifestRef expected
, SOSManifestRef computed
) {
66 appendManifestDescription(string
, prefix
, computed
);
67 if (CFEqualSafe(computed
, expected
)) {
72 appendManifestDescription(string
, CFSTR("!="), expected
);
77 static void test_okmfcomplement(SOSManifestRef r
, SOSManifestRef b
, SOSManifestRef n
, __attribute((cf_consumed
)) CFStringRef test_description
, const char *test_directive
, const char *reason
, const char *file
, unsigned line
, const char *fmt
, ...) {
78 CFErrorRef error
= NULL
;
80 CFMutableStringRef extendedDescription
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, test_description
);
81 if (test_description
&& CFStringGetLength(test_description
) != 0)
82 CFStringAppend(extendedDescription
, CFSTR(" "));
83 appendManifestDescription(extendedDescription
, CFSTR("complement "), r
);
84 appendManifestDescription(extendedDescription
, CFSTR("->"), b
);
85 SOSManifestRef
new = SOSManifestCreateComplement(r
, b
, &error
);
87 CFStringAppendFormat(extendedDescription
, NULL
, CFSTR(" SOSManifestCreateComplement: %@"), error
);
89 passed
= appendManifestComparison(extendedDescription
, CFSTR(" -> "), n
, new);
91 test_ok(passed
, extendedDescription
, test_directive
, test_reason
, file
, line
, NULL
);
92 CFReleaseSafe(test_description
);
97 static void test_okmfdiff(SOSManifestRef a
, SOSManifestRef b
, SOSManifestRef exp_a_b
, SOSManifestRef exp_b_a
, __attribute((cf_consumed
)) CFStringRef test_description
, const char *test_directive
, const char *reason
, const char *file
, unsigned line
, const char *fmt
, ...) {
98 CFErrorRef error
= NULL
;
99 SOSManifestRef a_minus_b
= NULL
;
100 SOSManifestRef b_minus_a
= NULL
;
102 CFMutableStringRef extendedDescription
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, test_description
);
103 if (test_description
&& CFStringGetLength(test_description
) != 0)
104 CFStringAppend(extendedDescription
, CFSTR(" "));
105 appendManifestDescription(extendedDescription
, CFSTR("diff "), a
);
106 appendManifestDescription(extendedDescription
, CFSTR("->"), b
);
107 if (!SOSManifestDiff(a
, b
, &a_minus_b
, &b_minus_a
, &error
)) {
108 CFStringAppendFormat(extendedDescription
, NULL
, CFSTR(" SOSManifestDiff: %@"), error
);
110 passed
= appendManifestComparison(extendedDescription
, CFSTR(" -> "), exp_a_b
, a_minus_b
);
111 passed
&= appendManifestComparison(extendedDescription
, CFSTR("->"), exp_b_a
, b_minus_a
);
113 test_ok(passed
, extendedDescription
, test_directive
, test_reason
, file
, line
, NULL
);
114 CFReleaseSafe(test_description
);
115 CFReleaseSafe(a_minus_b
);
116 CFReleaseSafe(b_minus_a
);
117 CFReleaseSafe(error
);
120 static void test_okmfintersection(SOSManifestRef a
, SOSManifestRef b
, SOSManifestRef n
, __attribute((cf_consumed
)) CFStringRef test_description
, const char *test_directive
, const char *reason
, const char *file
, unsigned line
, const char *fmt
, ...) {
121 CFErrorRef error
= NULL
;
123 CFMutableStringRef extendedDescription
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, test_description
);
124 if (test_description
&& CFStringGetLength(test_description
) != 0)
125 CFStringAppend(extendedDescription
, CFSTR(" "));
126 appendManifestDescription(extendedDescription
, CFSTR("intersection "), a
);
127 appendManifestDescription(extendedDescription
, CFSTR("->") /*CFSTR(" \xe2\x88\xa9 ")*/, b
);
128 SOSManifestRef
new = SOSManifestCreateIntersection(a
, b
, &error
);
130 CFStringAppendFormat(extendedDescription
, NULL
, CFSTR(" SOSManifestCreateIntersection: %@"), error
);
132 passed
= appendManifestComparison(extendedDescription
, CFSTR(" -> "), n
, new);
134 test_ok(passed
, extendedDescription
, test_directive
, test_reason
, file
, line
, NULL
);
135 CFReleaseSafe(test_description
);
137 CFReleaseSafe(error
);
140 static void test_okmfpatch(SOSManifestRef b
, SOSManifestRef r
, SOSManifestRef a
, SOSManifestRef n
, __attribute((cf_consumed
)) CFStringRef test_description
, const char *test_directive
, const char *reason
, const char *file
, unsigned line
, const char *fmt
, ...) {
141 CFErrorRef error
= NULL
;
143 CFMutableStringRef extendedDescription
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, test_description
);
144 if (test_description
&& CFStringGetLength(test_description
) != 0)
145 CFStringAppend(extendedDescription
, CFSTR(" "));
146 appendManifestDescription(extendedDescription
, CFSTR("patch "), b
);
147 appendManifestDescription(extendedDescription
, CFSTR("->"), r
);
148 appendManifestDescription(extendedDescription
, CFSTR("->"), a
);
149 SOSManifestRef
new = SOSManifestCreateWithPatch(b
, r
, a
, &error
);
151 CFStringAppendFormat(extendedDescription
, NULL
, CFSTR(" SOSManifestCreateWithPatch: %@"), error
);
153 passed
= appendManifestComparison(extendedDescription
, CFSTR(" -> "), n
, new);
155 test_ok(passed
, extendedDescription
, test_directive
, test_reason
, file
, line
, NULL
);
156 CFReleaseSafe(test_description
);
158 CFReleaseSafe(error
);
161 static void test_okmfunion(SOSManifestRef a
, SOSManifestRef b
, SOSManifestRef n
, __attribute((cf_consumed
)) CFStringRef test_description
, const char *test_directive
, const char *reason
, const char *file
, unsigned line
, const char *fmt
, ...) {
162 CFErrorRef error
= NULL
;
164 CFMutableStringRef extendedDescription
= CFStringCreateMutableCopy(kCFAllocatorDefault
, 0, test_description
);
165 if (test_description
&& CFStringGetLength(test_description
) != 0)
166 CFStringAppend(extendedDescription
, CFSTR(" "));
167 appendManifestDescription(extendedDescription
, CFSTR("union "), a
);
168 appendManifestDescription(extendedDescription
, CFSTR("->") /*CFSTR(" \xe2\x88\xaa ")*/, b
);
169 SOSManifestRef
new = SOSManifestCreateUnion(a
, b
, &error
);
171 CFStringAppendFormat(extendedDescription
, NULL
, CFSTR(" SOSManifestCreateUnion: %@"), error
);
173 passed
= appendManifestComparison(extendedDescription
, CFSTR(" -> "), n
, new);
175 test_ok(passed
, extendedDescription
, test_directive
, test_reason
, file
, line
, NULL
);
176 CFReleaseSafe(test_description
);
178 CFReleaseSafe(error
);
181 static SOSManifestRef
createManifestWithString(CFStringRef string
) {
182 struct SOSDigestVector dv
= SOSDigestVectorInit
;
183 CFIndex length
= string
? CFStringGetLength(string
) : 0;
184 CFStringInlineBuffer buf
= {};
185 CFRange range
= { 0, length
};
186 CFStringInitInlineBuffer(string
, &buf
, range
);
187 for (CFIndex ix
= 0; ix
< length
; ++ix
) {
188 uint8_t digest
[20] = " ";
189 UniChar c
= CFStringGetCharacterFromInlineBuffer(&buf
, ix
);
191 SOSDigestVectorAppend(&dv
, digest
);
193 SOSManifestRef mf
= NULL
;
194 mf
= SOSManifestCreateWithDigestVector(&dv
, NULL
);
195 SOSDigestVectorFree(&dv
);
199 static SOSManifestRef
testCreateBadManifest() {
200 SOSManifestRef mf
= createManifestWithString(CFSTR("bab"));
201 is(SOSManifestGetCount(mf
), (size_t)2, "dupes eliminated?");
206 typedef struct mf_vectors
{
208 SOSManifestRef empty
;
215 SOSManifestRef agghhjk
;
217 SOSManifestRef agghh
;
220 static void setupMF(mf_t
*mf
) {
221 CFErrorRef error
= NULL
;
223 mf
->empty
= SOSManifestCreateWithBytes(NULL
, 0, &error
);
224 mf
->a
= createManifestWithString(CFSTR("a"));
225 mf
->b
= createManifestWithString(CFSTR("b"));
226 mf
->ab
= createManifestWithString(CFSTR("ab"));
227 mf
->bab
= testCreateBadManifest();
228 mf
->gh
= createManifestWithString(CFSTR("gh"));
229 mf
->agh
= createManifestWithString(CFSTR("agh"));
230 mf
->agghhjk
= createManifestWithString(CFSTR("agghhjk"));
231 mf
->gghh
= createManifestWithString(CFSTR("gghh"));
232 mf
->agghh
= createManifestWithString(CFSTR("agghh"));
235 static void teardownMF(mf_t
*mf
) {
237 CFReleaseSafe(mf
->empty
);
238 CFReleaseSafe(mf
->a
);
239 CFReleaseSafe(mf
->b
);
240 CFReleaseSafe(mf
->ab
);
241 CFReleaseSafe(mf
->bab
);
242 CFReleaseSafe(mf
->gh
);
243 CFReleaseSafe(mf
->agh
);
244 CFReleaseSafe(mf
->agghhjk
);
245 CFReleaseSafe(mf
->gghh
);
246 CFReleaseSafe(mf
->agghh
);
249 static void testNullManifest(SOSManifestRef mf
)
251 is(SOSManifestGetCount(mf
), (size_t)0, "count is 0");
252 is(SOSManifestGetSize(mf
), (size_t)0, "capacity is 0");
255 static void testNull(mf_t
*mf
) {
256 testNullManifest(mf
->null
);
257 testNullManifest(mf
->empty
);
260 static void testDiff(mf_t
*mf
) {
261 okmfdiff(mf
->null
, mf
->null
, mf
->empty
, mf
->empty
);
262 okmfdiff(mf
->null
, mf
->empty
, mf
->empty
, mf
->empty
);
263 okmfdiff(mf
->null
, mf
->a
, mf
->empty
, mf
->a
);
264 okmfdiff(mf
->empty
, mf
->null
, mf
->empty
, mf
->empty
);
265 okmfdiff(mf
->empty
, mf
->empty
, mf
->empty
, mf
->empty
);
266 okmfdiff(mf
->empty
, mf
->a
, mf
->empty
, mf
->a
);
267 okmfdiff(mf
->a
, mf
->null
, mf
->a
, mf
->empty
);
268 okmfdiff(mf
->a
, mf
->empty
, mf
->a
, mf
->empty
);
269 okmfdiff(mf
->a
, mf
->a
, mf
->empty
, mf
->empty
);
270 okmfdiff(mf
->bab
, mf
->empty
, mf
->ab
, mf
->empty
);
271 okmfdiff(mf
->bab
, mf
->a
, mf
->b
, mf
->empty
);
272 okmfdiff(mf
->a
, mf
->bab
, mf
->empty
, mf
->b
);
273 okmfdiff(mf
->bab
, mf
->b
, mf
->a
, mf
->empty
);
274 okmfdiff(mf
->b
, mf
->bab
, mf
->empty
, mf
->a
);
275 okmfdiff(mf
->bab
, mf
->bab
, mf
->empty
, mf
->empty
);
278 static void testPatch(mf_t
*mf
) {
279 okmfpatch(mf
->null
, mf
->null
, mf
->null
, mf
->empty
);
280 okmfpatch(mf
->empty
, mf
->empty
, mf
->empty
, mf
->empty
);
281 okmfpatch(mf
->bab
, mf
->b
, mf
->a
, mf
->a
);
282 okmfpatch(mf
->ab
, mf
->empty
, mf
->empty
, mf
->ab
);
283 okmfpatch(mf
->ab
, mf
->empty
, mf
->a
, mf
->ab
);
284 okmfpatch(mf
->bab
, mf
->empty
, mf
->a
, mf
->ab
);
285 okmfpatch(mf
->bab
, mf
->ab
, mf
->null
, mf
->empty
);
286 okmfpatch(mf
->bab
, mf
->empty
, mf
->empty
, mf
->ab
);
289 static void testUnion(mf_t
*mf
) {
290 okmfunion(mf
->null
, mf
->null
, mf
->empty
);
291 okmfunion(mf
->null
, mf
->empty
, mf
->empty
);
292 okmfunion(mf
->empty
, mf
->null
, mf
->empty
);
293 okmfunion(mf
->empty
, mf
->empty
, mf
->empty
);
294 okmfunion(mf
->null
, mf
->a
, mf
->a
);
295 okmfunion(mf
->a
, mf
->null
, mf
->a
);
296 okmfunion(mf
->empty
, mf
->a
, mf
->a
);
297 okmfunion(mf
->a
, mf
->empty
, mf
->a
);
298 okmfunion(mf
->bab
, mf
->ab
, mf
->ab
);
299 okmfunion(mf
->empty
, mf
->bab
, mf
->ab
);
300 okmfunion(mf
->bab
, mf
->empty
, mf
->ab
);
303 static void testIntersect(mf_t
*mf
) {
304 okmfintersection(mf
->null
, mf
->null
, mf
->empty
);
305 okmfintersection(mf
->null
, mf
->empty
, mf
->empty
);
306 okmfintersection(mf
->empty
, mf
->null
, mf
->empty
);
307 okmfintersection(mf
->empty
, mf
->empty
, mf
->empty
);
308 okmfintersection(mf
->null
, mf
->a
, mf
->empty
);
309 okmfintersection(mf
->a
, mf
->null
, mf
->empty
);
310 okmfintersection(mf
->empty
, mf
->a
, mf
->empty
);
311 okmfintersection(mf
->a
, mf
->empty
, mf
->empty
);
312 okmfintersection(mf
->bab
, mf
->ab
, mf
->ab
);
313 okmfintersection(mf
->bab
, mf
->a
, mf
->a
);
314 okmfintersection(mf
->a
, mf
->bab
, mf
->a
);
315 okmfintersection(mf
->b
, mf
->bab
, mf
->b
);
316 okmfintersection(mf
->bab
, mf
->bab
, mf
->ab
);
317 okmfintersection(mf
->gghh
, mf
->agghh
, mf
->gh
);
318 okmfintersection(mf
->agghhjk
, mf
->agghh
, mf
->agh
);
321 static void testComplement(mf_t
*mf
) {
322 okmfcomplement(mf
->null
, mf
->null
, mf
->empty
);
323 okmfcomplement(mf
->null
, mf
->empty
, mf
->empty
);
324 okmfcomplement(mf
->empty
, mf
->null
, mf
->empty
);
325 okmfcomplement(mf
->empty
, mf
->empty
, mf
->empty
);
326 okmfcomplement(mf
->null
, mf
->a
, mf
->a
);
327 okmfcomplement(mf
->a
, mf
->null
, mf
->empty
);
328 okmfcomplement(mf
->empty
, mf
->a
, mf
->a
);
329 okmfcomplement(mf
->a
, mf
->empty
, mf
->empty
);
330 okmfcomplement(mf
->bab
, mf
->ab
, mf
->empty
);
331 okmfcomplement(mf
->ab
, mf
->bab
, mf
->empty
);
332 okmfcomplement(mf
->bab
, mf
->a
, mf
->empty
);
333 okmfcomplement(mf
->a
, mf
->bab
, mf
->b
);
334 okmfcomplement(mf
->b
, mf
->bab
, mf
->a
);
335 okmfcomplement(mf
->empty
, mf
->bab
, mf
->ab
);
338 static void tests(void)
353 int secd_49_manifests(int argc
, char *const *argv
)
355 plan_tests(kTestTestCount
);