]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSRingUtils.c
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSRingUtils.c
1 /*
2 * Copyright (c) 2015 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 * SOSRingUtils.c - Functions for building rings
27 */
28
29 #include <AssertMacros.h>
30
31 #include <Security/SecureObjectSync/SOSInternal.h>
32 #include <Security/SecureObjectSync/SOSPeer.h>
33 #include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
34 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
35 #include <Security/SecureObjectSync/SOSCircle.h>
36 #include <Security/SecFramework.h>
37
38 #include <Security/SecKey.h>
39 #include <Security/SecKeyPriv.h>
40 #include <CoreFoundation/CoreFoundation.h>
41
42 #include <utilities/SecCFWrappers.h>
43
44 //#include "ckdUtilities.h"
45
46 #include <corecrypto/ccder.h>
47 #include <corecrypto/ccdigest.h>
48 #include <corecrypto/ccsha2.h>
49
50
51 #include <utilities/der_plist.h>
52 #include <utilities/der_plist_internal.h>
53 #include <corecrypto/ccder.h>
54 #include <utilities/der_date.h>
55
56 #include <stdlib.h>
57 #include <assert.h>
58
59 #include "SOSRing.h"
60 #include "SOSRingUtils.h"
61
62 CFGiblisWithCompareFor(SOSRing);
63
64 /* unSignedInformation Dictionary Keys */
65 CFStringRef sApplicantsKey = CFSTR("Applicants");
66 CFStringRef sRejectionsKey = CFSTR("Rejections");
67 CFStringRef sLastPeerToModifyKey = CFSTR("LastModifier");
68
69 /* signedInformation Dictionary Keys */
70 CFStringRef sPeerIDsKey = CFSTR("PeerIDs");
71 CFStringRef sPayloadKey = CFSTR("Payload");
72 CFStringRef sBackupViewSetKey = CFSTR("BackupViews");
73 CFStringRef sGenerationKey = CFSTR("Generation");
74 CFStringRef sNameKey = CFSTR("RingName");
75 CFStringRef sTypeKey = CFSTR("RingType");
76 CFStringRef sIdentifierKey = CFSTR("Identifier");
77 CFStringRef sRingVersionKey = CFSTR("RingVersion");
78
79 #define RINGVERSION 1
80
81 SOSRingRef SOSRingAllocate(void) {
82 return (SOSRingRef) CFTypeAllocate(SOSRing, struct __OpaqueSOSRing, ALLOCATOR);
83 }
84
85 __unused static bool addValueToDict(CFMutableDictionaryRef thedict, CFStringRef key, CFTypeRef value) {
86 if(!value) return false;
87 CFDictionaryAddValue(thedict, key, value);
88 return true;
89 }
90
91 static bool setValueInDict(CFMutableDictionaryRef thedict, CFStringRef key, CFTypeRef value) {
92 if(!value) return false;
93 CFDictionarySetValue(thedict, key, value);
94 return true;
95 }
96
97 static CFMutableSetRef CFSetCreateMutableForSOSPeerIDs(void) {
98 return CFSetCreateMutable(ALLOCATOR, 0, &kCFTypeSetCallBacks);
99 }
100
101
102 static inline
103 SOSRingRef SOSRingConvertAndAssertStable(CFTypeRef ringAsType) {
104 if (CFGetTypeID(ringAsType) != SOSRingGetTypeID())
105 return NULL;
106
107 SOSRingRef ring = (SOSRingRef) ringAsType;
108
109 SOSRingAssertStable(ring);
110
111 return ring;
112 }
113
114 // MARK: Ring Name
115
116 CFStringRef SOSRingGetName(SOSRingRef ring) {
117 assert(ring);
118 assert(ring->signedInformation);
119 return asString(CFDictionaryGetValue(ring->signedInformation, sNameKey), NULL);
120 }
121
122 const char *SOSRingGetNameC(SOSRingRef ring) {
123 CFStringRef name = asString(SOSRingGetName(ring), NULL);
124 if (!name)
125 return strdup("");
126 return CFStringToCString(name);
127 }
128
129 static inline bool SOSRingSetName(SOSRingRef ring, CFStringRef name) {
130 assert(ring);
131 assert(ring->signedInformation);
132 return setValueInDict(ring->signedInformation, sNameKey, name);
133 }
134
135 // MARK: Ring Type
136
137 static bool SOSRingCheckType(SOSRingType type, CFErrorRef *error) {
138 if(type < kSOSRingTypeCount) return true;
139 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Bad Ring Type Specification"), (error != NULL) ? *error : NULL, error);
140 return false;
141 }
142
143 uint32_t SOSRingGetType(SOSRingRef ring) {
144 uint32_t retval = kSOSRingTypeError; // Error return
145 SOSRingAssertStable(ring);
146 if(!ring->signedInformation) return retval;
147 CFNumberRef ringtype = (CFNumberRef) CFDictionaryGetValue(ring->signedInformation, sTypeKey);
148 CFNumberGetValue(ringtype, kCFNumberSInt32Type, &retval);
149 return retval;
150 }
151
152 static inline bool SOSRingSetType(SOSRingRef ring, uint32_t ringtype) {
153 bool retval = false;
154 CFNumberRef cfrtype = NULL;
155 SOSRingAssertStable(ring);
156 require_action_quiet(SOSRingCheckType(ringtype, NULL), errOut, secnotice("ring", "Bad ring type specification"));
157 cfrtype = CFNumberCreate(ALLOCATOR, kCFNumberSInt32Type, &ringtype);
158 retval = setValueInDict(ring->signedInformation, sTypeKey, cfrtype);
159 errOut:
160 CFReleaseNull(cfrtype);
161 return retval;
162 }
163
164 // MARK: Version
165
166 uint32_t SOSRingGetVersion(SOSRingRef ring) {
167 uint32_t version = 0;
168 assert(ring);
169 assert(ring->signedInformation);
170 CFNumberRef cfversion = CFDictionaryGetValue(ring->signedInformation, sRingVersionKey);
171 require_action_quiet(cfversion, errOut, secnotice("ring", "Could not create version number"));
172 CFNumberGetValue(cfversion, kCFNumberSInt32Type, &version);
173 errOut:
174 return version;
175 }
176
177 static inline bool SOSRingSetVersion(SOSRingRef ring) {
178 assert(ring);
179 assert(ring->signedInformation);
180 int32_t thisversion = RINGVERSION;
181 CFNumberRef version = CFNumberCreate(ALLOCATOR, kCFNumberSInt32Type, &thisversion);
182 require_action_quiet(version, errOut, secnotice("ring", "Could not create version number"));
183 CFDictionarySetValue(ring->signedInformation, sRingVersionKey, version);
184 CFReleaseNull(version);
185 return true;
186 errOut:
187 return false;
188 }
189
190 // MARK: Identifier
191
192 CFStringRef SOSRingGetIdentifier(SOSRingRef ring) {
193 assert(ring);
194 assert(ring->signedInformation);
195 return CFDictionaryGetValue(ring->signedInformation, sIdentifierKey);
196 }
197
198 static inline bool SOSRingSetIdentifier(SOSRingRef ring) {
199 assert(ring);
200 assert(ring->signedInformation);
201 bool retval = false;
202 CFStringRef identifier = NULL;
203 CFUUIDRef uuid = CFUUIDCreate(ALLOCATOR);
204 require_action_quiet(uuid, errOut, secnotice("ring", "Could not create ring identifier"));
205 identifier = CFUUIDCreateString(ALLOCATOR, uuid);
206 CFDictionarySetValue(ring->signedInformation, sIdentifierKey, identifier);
207 retval = true;
208 errOut:
209 CFReleaseNull(uuid);
210 CFReleaseNull(identifier);
211 return retval;
212 }
213
214 // MARK: Ring Identity
215
216 bool SOSRingIsSame(SOSRingRef ring1, SOSRingRef ring2) {
217 CFStringRef name1 = SOSRingGetName(ring1);
218 CFStringRef name2 = SOSRingGetName(ring2);
219 require_action_quiet(name1 && name2, errOut, secnotice("ring", "Cannot get both names to consider rings the same"));
220 if(CFEqualSafe(name1, name2) != true) return false;
221
222 #if 0
223 // Not considering this for now - upgraded version can still be the "same ring".
224 uint32_t version1 = SOSRingGetVersion(ring1);
225 uint32_t version2 = SOSRingGetVersion(ring2);
226 require_action_quiet(version1 && version2, errOut, secnotice("ring", "Cannot get both versions to consider rings the same"));
227 if(version1 != version2) return false;
228 #endif
229
230 uint32_t type1 = SOSRingGetType(ring1);
231 uint32_t type2 = SOSRingGetVersion(ring2);
232 require_action_quiet(type1 && type2, errOut, secnotice("ring", "Cannot get both types to consider rings the same"));
233 if(type1 != type2) return false;
234
235 CFStringRef identifier1 = SOSRingGetIdentifier(ring1);
236 CFStringRef identifier2 = SOSRingGetIdentifier(ring2);
237 require_action_quiet(identifier1 && identifier2, errOut, secnotice("ring", "Cannot get both identifiers to consider rings the same"));
238 if(CFEqualSafe(identifier1, identifier2) != true) return false;
239
240 return true;
241 errOut:
242 return false;
243
244 }
245
246 static Boolean SOSRingCompare(CFTypeRef lhs, CFTypeRef rhs) {
247 if (CFGetTypeID(lhs) != SOSRingGetTypeID()
248 || CFGetTypeID(rhs) != SOSRingGetTypeID())
249 return false;
250
251 SOSRingRef left = SOSRingConvertAndAssertStable(lhs);
252 SOSRingRef right = SOSRingConvertAndAssertStable(rhs);
253
254 return NULL != left && NULL != right
255 && CFEqualSafe(left->unSignedInformation, right->unSignedInformation)
256 && CFEqualSafe(left->signedInformation, right->signedInformation)
257 && CFEqualSafe(left->data, right->data)
258 && CFEqualSafe(left->signatures, right->signatures);
259 }
260
261
262 // MARK: Ring Generation Count
263
264 SOSGenCountRef SOSRingGetGeneration(SOSRingRef ring) {
265 assert(ring);
266 assert(ring->signedInformation);
267 return CFDictionaryGetValue(ring->signedInformation, sGenerationKey);
268 }
269
270 static inline bool SOSRingSetGeneration(SOSRingRef ring, SOSGenCountRef gen) {
271 assert(ring);
272 assert(ring->signedInformation);
273 return setValueInDict(ring->signedInformation, sGenerationKey, gen);
274 }
275
276 void SOSRingGenerationIncrement(SOSRingRef ring) {
277 SOSGenCountRef gen = SOSRingGetGeneration(ring);
278 SOSGenCountRef newgen = SOSGenerationIncrementAndCreate(gen);
279 SOSRingSetGeneration(ring, newgen);
280 CFReleaseNull(newgen);
281 }
282
283 bool SOSRingIsOlderGeneration(SOSRingRef olderRing, SOSRingRef newerRing) {
284 SOSGenCountRef old = SOSRingGetGeneration(olderRing);
285 SOSGenCountRef new = SOSRingGetGeneration(newerRing);
286 return SOSGenerationIsOlder(old, new);
287 }
288
289 void SOSRingGenerationCreateWithBaseline(SOSRingRef newring, SOSRingRef baseline) {
290 if(!newring) return;
291 SOSGenCountRef gen = SOSGenerationCreateWithBaseline(SOSRingGetGeneration(baseline));
292 SOSRingSetGeneration(newring, gen);
293 CFReleaseNull(gen);
294 }
295
296 // MARK: Last Modifier
297 CFStringRef SOSRingGetLastModifier(SOSRingRef ring) {
298 assert(ring);
299 assert(ring->unSignedInformation);
300 return CFDictionaryGetValue(ring->unSignedInformation, sLastPeerToModifyKey);
301 }
302
303 bool SOSRingSetLastModifier(SOSRingRef ring, CFStringRef peerID) {
304 assert(ring);
305 assert(ring->unSignedInformation);
306 return setValueInDict(ring->unSignedInformation, sLastPeerToModifyKey, peerID);
307 }
308
309
310 // MARK: Ring Applicants
311
312 CFMutableSetRef SOSRingGetApplicants(SOSRingRef ring) {
313 SOSRingAssertStable(ring);
314 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sApplicantsKey);
315 }
316
317 bool SOSRingSetApplicants(SOSRingRef ring, CFMutableSetRef applicants) {
318 SOSRingAssertStable(ring);
319 return setValueInDict(ring->unSignedInformation, sApplicantsKey, applicants);
320 }
321
322 int SOSRingCountApplicants(SOSRingRef ring) {
323 SOSRingAssertStable(ring);
324 return (int)CFSetGetCount(SOSRingGetApplicants(ring));
325 }
326
327 bool SOSRingHasApplicant(SOSRingRef ring, CFStringRef peerID) {
328 SOSRingAssertStable(ring);
329 return CFSetContainsValue(SOSRingGetApplicants(ring), peerID);
330 }
331
332 CFMutableSetRef SOSRingCopyApplicants(SOSRingRef ring) {
333 SOSRingAssertStable(ring);
334 CFSetRef applicants = SOSRingGetApplicants(ring);
335 return CFSetCreateMutableCopy(ALLOCATOR, 0, applicants);
336 }
337
338 bool SOSRingAddApplicant(SOSRingRef ring, CFStringRef peerid) {
339 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
340 CFSetAddValue(applicants, peerid);
341 return true;
342 }
343
344 bool SOSRingRemoveApplicant(SOSRingRef ring, CFStringRef peerid) {
345 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
346 CFSetRemoveValue(applicants, peerid);
347 return true;
348 }
349
350 // MARK: Ring Rejections
351
352 static inline CFMutableSetRef SOSRingGetRejections(SOSRingRef ring) {
353 SOSRingAssertStable(ring);
354 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sRejectionsKey);
355 }
356
357 static inline bool SOSRingSetRejections(SOSRingRef ring, CFMutableSetRef rejections) {
358 SOSRingAssertStable(ring);
359 return setValueInDict(ring->unSignedInformation, sRejectionsKey, rejections);
360 }
361
362 int SOSRingCountRejections(SOSRingRef ring) {
363 CFSetRef rejects = SOSRingGetRejections(ring);
364 return (int)CFSetGetCount(rejects);
365 }
366
367 bool SOSRingHasRejection(SOSRingRef ring, CFStringRef peerID) {
368 SOSRingAssertStable(ring);
369 return CFSetContainsValue(SOSRingGetRejections(ring), peerID);
370 }
371
372 CFMutableSetRef SOSRingCopyRejections(SOSRingRef ring) {
373 CFSetRef rejects = SOSRingGetRejections(ring);
374 return CFSetCreateMutableCopy(ALLOCATOR, 0, rejects);
375 }
376
377
378 bool SOSRingAddRejection(SOSRingRef ring, CFStringRef peerid) {
379 CFMutableSetRef rejects = SOSRingGetRejections(ring);
380 CFSetAddValue(rejects, peerid);
381 return true;
382 }
383
384 bool SOSRingRemoveRejection(SOSRingRef ring, CFStringRef peerid) {
385 CFMutableSetRef rejects = SOSRingGetRejections(ring);
386 CFSetRemoveValue(rejects, peerid);
387 return true;
388 }
389
390 // MARK: Ring Payload
391
392 CFDataRef SOSRingGetPayload_Internal(SOSRingRef ring) {
393 SOSRingAssertStable(ring);
394 return (CFDataRef) CFDictionaryGetValue(ring->signedInformation, sPayloadKey);
395 }
396
397 bool SOSRingSetPayload_Internal(SOSRingRef ring, CFDataRef payload) {
398 SOSRingAssertStable(ring);
399 return setValueInDict(ring->signedInformation, sPayloadKey, payload);
400 }
401
402 // MARK: Ring Backup Viewset
403
404
405 CFSetRef SOSRingGetBackupViewset_Internal(SOSRingRef ring) {
406 SOSRingAssertStable(ring);
407 return asSet(CFDictionaryGetValue(ring->signedInformation, sBackupViewSetKey), NULL);
408 }
409
410 bool SOSRingSetBackupViewset_Internal(SOSRingRef ring, CFSetRef viewSet) {
411 SOSRingAssertStable(ring);
412 return setValueInDict(ring->signedInformation, sBackupViewSetKey, viewSet);
413 }
414
415
416
417 // MARK: Ring PeerIDs
418
419 static inline CFMutableSetRef SOSRingGetPeerIDs(SOSRingRef ring) {
420 SOSRingAssertStable(ring);
421 return (CFMutableSetRef) asSet(CFDictionaryGetValue(ring->signedInformation, sPeerIDsKey), NULL);
422 }
423
424 bool SOSRingSetPeerIDs(SOSRingRef ring, CFMutableSetRef peers) {
425 SOSRingAssertStable(ring);
426 return setValueInDict(ring->signedInformation, sPeerIDsKey, peers);
427 }
428
429 int SOSRingCountPeerIDs(SOSRingRef ring) {
430 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
431 return (int)CFSetGetCount(peerIDs);
432 }
433
434
435 bool SOSRingHasPeerID(SOSRingRef ring, CFStringRef peerID) {
436 SOSRingAssertStable(ring);
437 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerID);
438 }
439
440 CFMutableSetRef SOSRingCopyPeerIDs(SOSRingRef ring) {
441 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
442 return CFSetCreateMutableCopy(ALLOCATOR, 0, peerIDs);
443 }
444
445 void SOSRingAddAll(SOSRingRef ring, CFSetRef peerInfosOrIDs) {
446 CFSetForEach(peerInfosOrIDs, ^(const void *value) {
447 CFStringRef peerID = value;
448
449 if (isSOSPeerInfo(value))
450 peerID = SOSPeerInfoGetPeerID((SOSPeerInfoRef)value);
451
452 if (isString(peerID))
453 SOSRingAddPeerID(ring, peerID);
454 });
455 }
456
457 bool SOSRingAddPeerID(SOSRingRef ring, CFStringRef peerid) {
458 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
459 CFSetAddValue(peerIDs, peerid);
460 return true;
461 }
462
463 bool SOSRingRemovePeerID(SOSRingRef ring, CFStringRef peerid) {
464 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
465 CFSetRemoveValue(peerIDs, peerid);
466 return true;
467 }
468
469 void SOSRingForEachPeerID(SOSRingRef ring, void (^action)(CFStringRef peerID)) {
470 SOSRingAssertStable(ring);
471 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
472 if(!peerIDs) return;
473 CFSetForEach(peerIDs, ^(const void*value) {
474 CFStringRef peerID = (CFStringRef) value;
475 action(peerID);
476 });
477 }
478
479 // MARK: SOSRing Ops
480
481 SOSRingRef SOSRingCreate_Internal(CFStringRef name, SOSRingType type, CFErrorRef *error) {
482 SOSRingRef r = SOSRingAllocate();
483 SOSGenCountRef gen = SOSGenerationCreate();
484
485 require_action_quiet(name, errout0,
486 SOSCreateError(kSOSErrorNoCircleName, CFSTR("No ring name"), NULL, error));
487 require_action_quiet(SOSRingCheckType(type, error), errout0,
488 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Unknown ring type"), NULL, error));
489 require_action_quiet((r->unSignedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
490 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate unsigned information area"), NULL, error));
491 require_action_quiet((r->signedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
492 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signed information area"), NULL, error));
493 require_action_quiet((r->signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
494 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signature area"), NULL, error));
495 require_action_quiet((r->data = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
496 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate data area"), NULL, error));
497
498 require_action_quiet(SOSRingSetName(r, name), errout,
499 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring name area"), NULL, error));
500 require_action_quiet(SOSRingSetType(r, type), errout,
501 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring type"), NULL, error));
502 require_action_quiet(SOSRingSetVersion(r), errout,
503 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring version"), NULL, error));
504 require_action_quiet(SOSRingSetIdentifier(r), errout,
505 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring identifier"), NULL, error));
506
507 CFMutableSetRef peerIDs = CFSetCreateMutableForSOSPeerIDs();
508 require_action_quiet(SOSRingSetApplicants(r, peerIDs), errout,
509 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate applicant area"), NULL, error));
510 CFReleaseNull(peerIDs);
511
512 CFMutableSetRef rejectedIDs = CFSetCreateMutableForSOSPeerIDs();
513 require_action_quiet(SOSRingSetRejections(r, rejectedIDs), errout,
514 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate rejection area"), NULL, error));
515 CFReleaseNull(rejectedIDs);
516
517 require_action_quiet(SOSRingSetGeneration(r, gen), errout,
518 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate generation count"), NULL, error));
519
520 peerIDs = CFSetCreateMutableForSOSPeerIDs();
521 require_action_quiet(SOSRingSetPeerIDs(r, peerIDs), errout,
522 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate PeerID"), NULL, error));
523 CFReleaseNull(gen);
524 CFReleaseNull(peerIDs);
525
526 return r;
527 errout:
528 CFReleaseNull(r->unSignedInformation);
529 CFReleaseNull(r->signedInformation);
530 CFReleaseNull(r->signatures);
531 CFReleaseNull(r->data);
532 errout0:
533 CFReleaseNull(gen);
534 CFReleaseNull(r);
535 return NULL;
536 }
537
538
539 static void SOSRingDestroy(CFTypeRef aObj) {
540 SOSRingRef c = (SOSRingRef) aObj;
541
542 CFReleaseNull(c->unSignedInformation);
543 CFReleaseNull(c->signedInformation);
544 CFReleaseNull(c->data);
545 CFReleaseNull(c->signatures);
546 }
547
548
549 SOSRingRef SOSRingCopyRing(SOSRingRef original, CFErrorRef *error) {
550 SOSRingRef r = CFTypeAllocate(SOSRing, struct __OpaqueSOSRing, ALLOCATOR);
551
552 assert(original);
553 r->unSignedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->unSignedInformation);
554 r->signedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signedInformation);
555 r->signatures = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signatures);
556 r->data = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->data);
557
558 return r;
559 }
560
561 bool SOSRingIsEmpty_Internal(SOSRingRef ring) {
562 return CFSetGetCount(SOSRingGetPeerIDs(ring)) == 0;
563 }
564
565 bool SOSRingIsOffering_Internal(SOSRingRef ring) {
566 return SOSRingCountPeers(ring) == 1;
567 }
568
569 bool SOSRingResetToEmpty_Internal(SOSRingRef ring, CFErrorRef *error) {
570 SOSGenCountRef gen = NULL;
571 CFSetRemoveAllValues(SOSRingGetApplicants(ring));
572 CFSetRemoveAllValues(SOSRingGetRejections(ring));
573 CFSetRemoveAllValues(SOSRingGetPeerIDs(ring));
574 CFDictionaryRemoveAllValues(ring->signatures);
575 SOSRingSetGeneration(ring, gen = SOSGenerationCreate());
576 CFReleaseNull(gen);
577 return true;
578 }
579
580 // MARK: PeerIDs in Ring
581
582 #if 0
583 static inline bool isHiddenPeer(SOSPeerInfoRef peer) {
584 return SOSPeerInfoIsRetirementTicket(peer) || SOSPeerInfoIsCloudIdentity(peer);
585 }
586 #endif
587
588 int SOSRingCountPeers(SOSRingRef ring) {
589 SOSRingAssertStable(ring);
590 return (int) CFSetGetCount(SOSRingGetPeerIDs(ring));
591 }
592
593
594 bool SOSRingHasPeerWithID(SOSRingRef ring, CFStringRef peerid, CFErrorRef *error) {
595 SOSRingAssertStable(ring);
596 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerid);
597 }
598
599 // MARK: Ring Signatures
600
601
602 static inline CFDictionaryRef SOSRingGetSignatures(SOSRingRef ring) {
603 return ring->signatures;
604 }
605
606 static inline CFDataRef SOSRingGetSignatureForPeerID(SOSRingRef ring, CFStringRef peerID) {
607 if(!ring || !peerID) return NULL;
608 CFDataRef result = NULL;
609 CFTypeRef value = (CFDataRef)CFDictionaryGetValue(SOSRingGetSignatures(ring), peerID);
610 if (isData(value)) result = (CFDataRef) value;
611 return result;
612 }
613
614 static CFDataRef SOSRingCreateHash(const struct ccdigest_info *di, SOSRingRef ring, CFErrorRef *error) {
615 uint8_t hash_result[di->output_size];
616
617 size_t dersize = der_sizeof_plist(ring->signedInformation, error);
618 if(dersize == 0) {
619 return false;
620 }
621 uint8_t der[dersize];
622 der_encode_plist(ring->signedInformation, error, der, der+dersize);
623
624 ccdigest(di, dersize, der, hash_result);
625 return CFDataCreate(NULL, hash_result, di->output_size);
626 }
627
628 static bool SOSRingSetSignature(SOSRingRef ring, SecKeyRef privKey, CFDataRef signature, CFErrorRef *error) {
629 bool result = false;
630 SecKeyRef pubkey = SecKeyCreatePublicFromPrivate(privKey);
631 CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error);
632 require_quiet(pubKeyID, fail);
633 CFDictionarySetValue(ring->signatures, pubKeyID, signature);
634 result = true;
635 fail:
636 CFReleaseSafe(pubkey);
637 CFReleaseSafe(pubKeyID);
638 return result;
639 }
640
641 static bool SOSRingRemoveSignatures(SOSRingRef ring, CFErrorRef *error) {
642 CFDictionaryRemoveAllValues(ring->signatures);
643 return true;
644 }
645
646 static CFDataRef SOSCopySignedHash(SecKeyRef privKey, CFDataRef hash, CFErrorRef *error) {
647 size_t siglen = SecKeyGetSize(privKey, kSecKeySignatureSize)+16;
648 uint8_t sig[siglen];
649 OSStatus stat = SecKeyRawSign(privKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash), sig, &siglen);
650 if(stat) {
651 return NULL;
652 }
653 return CFDataCreate(NULL, sig, siglen);
654 }
655
656 static bool SOSRingSign(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
657 if (!ring || !privKey) {
658 SOSCreateError(kSOSErrorBadSignature, CFSTR("SOSRingSign Lacking ring or private key"),
659 (error != NULL) ? *error : NULL, error);
660 return false;
661 }
662 const struct ccdigest_info *di = ccsha256_di();
663 CFDataRef hash = SOSRingCreateHash(di, ring, error);
664 CFDataRef signature = SOSCopySignedHash(privKey, hash, error);
665 SOSRingSetSignature(ring, privKey, signature, error);
666 CFRelease(signature);
667 CFReleaseNull(hash);
668 return true;
669 }
670
671 bool SOSRingVerifySignatureExists(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
672 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
673 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
674 CFReleaseNull(pubKeyID);
675 return NULL != signature;
676 }
677
678 bool SOSRingVerify(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
679 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
680 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
681 CFReleaseNull(pubKeyID);
682 if(!signature) return false;
683 CFDataRef hash = SOSRingCreateHash(ccsha256_di(), ring, error);
684 bool success = SecKeyRawVerify(pubKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash),
685 CFDataGetBytePtr(signature), CFDataGetLength(signature)) == errSecSuccess;
686 CFReleaseNull(hash);
687 return success;
688 }
689
690 bool SOSRingVerifyPeerSigned(SOSRingRef ring, SOSPeerInfoRef peer, CFErrorRef *error) {
691 bool result = false;
692 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(peer, error);
693 require_quiet(pubkey, fail);
694
695 result = SOSRingVerify(ring, pubkey, error);
696
697 fail:
698 CFReleaseSafe(pubkey);
699 return result;
700 }
701
702 static bool SOSRingEnsureRingConsistency(SOSRingRef ring, CFErrorRef *error) {
703 secnotice("Development", "SOSRingEnsureRingConsistency requires ring membership and generation count consistency check", NULL);
704 return true;
705 }
706
707 bool SOSRingGenerationSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
708 if(!privKey || !ring) return false;
709 bool retval = false;
710 SOSRingGenerationIncrement(ring);
711 require_quiet(SOSRingEnsureRingConsistency(ring, error), fail);
712 require_quiet(SOSRingRemoveSignatures(ring, error), fail);
713 require_quiet(SOSRingSign(ring, privKey, error), fail);
714 retval = true;
715 fail:
716 return retval;
717 }
718
719 // MARK: Concordance
720
721 bool SOSRingConcordanceSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
722 if(!privKey || !ring) return false;
723 bool retval = false;
724 require_quiet(SOSRingSign(ring, privKey, error), fail);
725 retval = true;
726 fail:
727 return retval;
728 }
729
730
731
732 // MARK: Debugging
733
734 static inline void CFSetForEachPeerID(CFSetRef set, void (^operation)(CFStringRef peerID)) {
735 CFSetForEach(set, ^(const void *value) {
736 CFStringRef peerID = (CFStringRef) value;
737 operation(peerID);
738 });
739 }
740
741 static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) {
742 CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0);
743
744 __block bool addSeparator = false;
745
746 CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
747 if (addSeparator) {
748 CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
749 }
750 CFStringAppend(result, peerID);
751
752 addSeparator = true;
753 });
754
755 return result;
756 }
757
758 CFDictionaryRef SOSRingCopyPeerIDList(SOSRingRef ring) {
759 CFStringRef peerIDS = CreateCommaSeparatedPeerIDs(SOSRingGetPeerIDs(ring));
760 CFStringRef applicantIDs = CreateCommaSeparatedPeerIDs(SOSRingGetApplicants(ring));
761 CFStringRef rejectIDs = CreateCommaSeparatedPeerIDs(SOSRingGetRejections(ring));
762 CFDictionaryRef list = CFDictionaryCreateForCFTypes(ALLOCATOR,
763 CFSTR("MEMBER"), peerIDS,
764 CFSTR("APPLICANTS"), applicantIDs,
765 CFSTR("REJECTS"), rejectIDs,
766 NULL);
767
768 CFReleaseNull(peerIDS);
769 CFReleaseNull(applicantIDs);
770 CFReleaseNull(rejectIDs);
771 return list;
772 }
773
774 CFStringRef SOSRingCopySignerList(SOSRingRef ring) {
775 __block bool addSeparator = false;
776 CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0);
777 CFDictionaryForEach(ring->signatures, ^(const void *key, const void *value) {
778 CFStringRef peerID = (CFStringRef) key;
779 if (addSeparator)
780 CFStringAppendCString(signers, ", ", kCFStringEncodingUTF8);
781 CFStringAppend(signers, peerID);
782 addSeparator = true;
783 });
784 return signers;
785 }
786
787 static CFStringRef SOSRingCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOpts) {
788 SOSRingRef ring = (SOSRingRef) aObj;
789
790 SOSRingAssertStable(ring);
791
792 CFDictionaryRef peers = SOSRingCopyPeerIDList(ring);
793 CFStringRef signers = SOSRingCopySignerList(ring);
794
795 CFDataRef payload = SOSRingGetPayload(ring, NULL);
796
797 CFStringRef gcString = SOSGenerationCountCopyDescription(SOSRingGetGeneration(ring));
798
799 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
800
801 CFStringAppendFormat(description, formatOpts, CFSTR("<SOSRing@%p: '%@', Version %u, "), ring, SOSRingGetName(ring), SOSRingGetVersion(ring));
802 CFStringAppendFormat(description, formatOpts, CFSTR("UUID: %@, "), SOSRingGetIdentifier(ring));
803 SOSGenerationCountWithDescription(SOSRingGetGeneration(ring), ^(CFStringRef gcString) {
804 CFStringAppendFormat(description, formatOpts, CFSTR("Gen: %@, "), gcString);
805 });
806 CFStringAppendFormat(description, formatOpts, CFSTR("Mod: %@, "), SOSRingGetLastModifier(ring));
807
808 CFStringAppendFormat(description, formatOpts, CFSTR("D: %ld "), payload ? CFDataGetLength(payload) : 0);
809
810 SOSBackupSliceKeyBagRef payloadAsBSKB = SOSRingCopyBackupSliceKeyBag(ring, NULL);
811
812 if (payloadAsBSKB) {
813 CFStringAppendFormat(description, formatOpts, CFSTR("%@ "), payloadAsBSKB);
814 }
815
816 CFReleaseSafe(payloadAsBSKB);
817
818 CFStringAppendFormat(description, formatOpts, CFSTR("P: [%@], "), CFDictionaryGetValue(peers, CFSTR("MEMBER")));
819 CFStringAppendFormat(description, formatOpts, CFSTR("A: [%@], "), CFDictionaryGetValue(peers, CFSTR("APPLICANTS")));
820 CFStringAppendFormat(description, formatOpts, CFSTR("R: [%@], "), CFDictionaryGetValue(peers, CFSTR("REJECTS")));
821 CFStringAppendFormat(description, formatOpts, CFSTR("S: [%@]>"), signers);
822
823 CFReleaseNull(gcString);
824 CFReleaseNull(peers);
825 CFReleaseNull(signers);
826 CFReleaseNull(peers);
827
828 return description;
829 }
830
831 //
832 // Peer Retirement
833 //
834
835 #define SIGLEN 128
836 #if 0
837 static CFDataRef sosSignHash(SecKeyRef privkey, const struct ccdigest_info *di, uint8_t *hbuf) {
838 OSStatus stat;
839 size_t siglen = SIGLEN;
840 uint8_t sig[siglen];
841 if((stat = SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen)) != 0) {
842 return NULL;
843 }
844 return CFDataCreate(NULL, sig, (CFIndex)siglen);
845 }
846 #endif
847 #if 0
848 static void WithBufferSpace(size_t space, void (^action)(uint8_t *buffer, size_t length)) {
849 if (space == 0) {
850 action(NULL, space);
851 } else if (space <= 2048) {
852 uint8_t buffer[space];
853
854 action(buffer, space);
855 } else {
856 uint8_t* buffer = malloc(space);
857
858 action(buffer, space);
859
860 free(buffer);
861 }
862 }
863
864 static CFDataRef CFDictionaryHashCreate(CFDictionaryRef dict, CFErrorRef *error) {
865
866 __block CFDataRef result = NULL;
867
868 require_quiet(dict, errOut);
869
870 WithBufferSpace(der_sizeof_dictionary(dict, error), ^(uint8_t *der, size_t len) {
871 if (len > 0) {
872 const struct ccdigest_info *di = ccsha256_di();
873 uint8_t hash_result[di->output_size];
874 der_encode_dictionary(dict, error, der, der+len);
875
876 ccdigest(di, len, der, hash_result);
877 result = CFDataCreate(ALLOCATOR, hash_result, di->output_size);
878 }
879 });
880
881 errOut:
882 return NULL;
883 }
884 #endif
885 /*
886 CFDictionary:
887 signatures: CFDictionary of key = hash(pubkey), value = signature(privkey, (DER(payload))
888 payload: CFDictionary passed in
889
890
891 */
892 #if 0
893 static CFStringRef sPayload = CFSTR("payload");
894 static CFStringRef sSignature = CFSTR("signature");
895
896 static bool SOSCFSignedDictionarySetSignature(SecKeyRef priv, CFDictionaryRef sd, CFErrorRef *error) {
897 CFDictionaryRef payload = CFDictionaryGetValue(sd, sPayload);
898 CFMutableDictionaryRef signatures = (CFMutableDictionaryRef) CFDictionaryGetValue(sd, sSignature);
899 CFDataRef hash = CFDictionaryHashCreate(payload, error);
900 CFDataRef signature = SOSHashSign(priv, hash, error);
901 CFReleaseNull(hash);
902 CFStringRef pubhash = SOSCopyIDOfKey(priv, error);
903 require_quiet(signature && pubhash, errOut);
904 CFDictionaryAddValue(signatures, pubhash, signature);
905 return true;
906 errOut:
907 return false;
908 }
909 #endif
910 #if 0
911 static CFDictionaryRef SOSCFSignedDictionaryCreate(SecKeyRef priv, CFDictionaryRef payload, CFErrorRef *error) {
912 CFMutableDictionaryRef signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
913 CFMutableDictionaryRef retval = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
914 require_quiet(signatures && retval, errOut);
915
916 CFDictionaryAddValue(retval, sSignature, signatures);
917 CFDictionaryAddValue(retval, sPayload, payload);
918 SOSCFSignedDictionarySetSignature(priv, retval, error);
919 return retval;
920 errOut:
921 CFReleaseNull(signatures);
922 CFReleaseNull(retval);
923 return NULL;
924 }
925 #endif
926
927 #if 0
928 CFDictionaryRef SOSRingCreateRetirementTicket(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
929 CFDictionaryRef retval = NULL;
930 CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpi));
931 SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(fpi, error);
932 CFDataRef resignationDate = SOSDateCreate();
933 GENCOUNT!!!
934
935 CFDataRef sig = SOSDERAndSignStuff(priv, keys, values, 2, error);
936 retval = CFDictionaryCreate(ALLOCATOR, <#const void **keys#>, <#const void **values#>, <#CFIndex numValues#>, <#const CFDictionaryKeyCallBacks *keyCallBacks#>, <#const CFDictionaryValueCallBacks *valueCallBacks#>)
937 return pi;
938
939 exit_stage_right:
940 CFReleaseNull(priv);
941 CFReleaseNull(resignationDate);
942 return retval;
943 }
944 #endif