]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ProjectHeaders/Security/SecureObjectSync/SOSRingUtils.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / ProjectHeaders / Security / 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 CFDictionaryGetValue(ring->signedInformation, sNameKey);
120 }
121
122 const char *SOSRingGetNameC(SOSRingRef ring) {
123 CFStringRef name = SOSRingGetName(ring);
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 // MARK: Last Modifier
290 CFStringRef SOSRingGetLastModifier(SOSRingRef ring) {
291 assert(ring);
292 assert(ring->unSignedInformation);
293 return CFDictionaryGetValue(ring->unSignedInformation, sLastPeerToModifyKey);
294 }
295
296 bool SOSRingSetLastModifier(SOSRingRef ring, CFStringRef peerID) {
297 assert(ring);
298 assert(ring->unSignedInformation);
299 return setValueInDict(ring->unSignedInformation, sLastPeerToModifyKey, peerID);
300 }
301
302
303 // MARK: Ring Applicants
304
305 CFMutableSetRef SOSRingGetApplicants(SOSRingRef ring) {
306 SOSRingAssertStable(ring);
307 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sApplicantsKey);
308 }
309
310 bool SOSRingSetApplicants(SOSRingRef ring, CFMutableSetRef applicants) {
311 SOSRingAssertStable(ring);
312 return setValueInDict(ring->unSignedInformation, sApplicantsKey, applicants);
313 }
314
315 int SOSRingCountApplicants(SOSRingRef ring) {
316 SOSRingAssertStable(ring);
317 return (int)CFSetGetCount(SOSRingGetApplicants(ring));
318 }
319
320 bool SOSRingHasApplicant(SOSRingRef ring, CFStringRef peerID) {
321 SOSRingAssertStable(ring);
322 return CFSetContainsValue(SOSRingGetApplicants(ring), peerID);
323 }
324
325 CFMutableSetRef SOSRingCopyApplicants(SOSRingRef ring) {
326 SOSRingAssertStable(ring);
327 CFSetRef applicants = SOSRingGetApplicants(ring);
328 return CFSetCreateMutableCopy(ALLOCATOR, 0, applicants);
329 }
330
331 bool SOSRingAddApplicant(SOSRingRef ring, CFStringRef peerid) {
332 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
333 CFSetAddValue(applicants, peerid);
334 return true;
335 }
336
337 bool SOSRingRemoveApplicant(SOSRingRef ring, CFStringRef peerid) {
338 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
339 CFSetRemoveValue(applicants, peerid);
340 return true;
341 }
342
343 // MARK: Ring Rejections
344
345 static inline CFMutableSetRef SOSRingGetRejections(SOSRingRef ring) {
346 SOSRingAssertStable(ring);
347 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sRejectionsKey);
348 }
349
350 static inline bool SOSRingSetRejections(SOSRingRef ring, CFMutableSetRef rejections) {
351 SOSRingAssertStable(ring);
352 return setValueInDict(ring->unSignedInformation, sRejectionsKey, rejections);
353 }
354
355 int SOSRingCountRejections(SOSRingRef ring) {
356 CFSetRef rejects = SOSRingGetRejections(ring);
357 return (int)CFSetGetCount(rejects);
358 }
359
360 bool SOSRingHasRejection(SOSRingRef ring, CFStringRef peerID) {
361 SOSRingAssertStable(ring);
362 return CFSetContainsValue(SOSRingGetRejections(ring), peerID);
363 }
364
365 CFMutableSetRef SOSRingCopyRejections(SOSRingRef ring) {
366 CFSetRef rejects = SOSRingGetRejections(ring);
367 return CFSetCreateMutableCopy(ALLOCATOR, 0, rejects);
368 }
369
370
371 bool SOSRingAddRejection(SOSRingRef ring, CFStringRef peerid) {
372 CFMutableSetRef rejects = SOSRingGetRejections(ring);
373 CFSetAddValue(rejects, peerid);
374 return true;
375 }
376
377 bool SOSRingRemoveRejection(SOSRingRef ring, CFStringRef peerid) {
378 CFMutableSetRef rejects = SOSRingGetRejections(ring);
379 CFSetRemoveValue(rejects, peerid);
380 return true;
381 }
382
383 // MARK: Ring Payload
384
385 CFDataRef SOSRingGetPayload_Internal(SOSRingRef ring) {
386 SOSRingAssertStable(ring);
387 return (CFDataRef) CFDictionaryGetValue(ring->signedInformation, sPayloadKey);
388 }
389
390 bool SOSRingSetPayload_Internal(SOSRingRef ring, CFDataRef payload) {
391 SOSRingAssertStable(ring);
392 return setValueInDict(ring->signedInformation, sPayloadKey, payload);
393 }
394
395 // MARK: Ring Backup Viewset
396
397
398 CFSetRef SOSRingGetBackupViewset_Internal(SOSRingRef ring) {
399 SOSRingAssertStable(ring);
400 return (CFSetRef) CFDictionaryGetValue(ring->signedInformation, sBackupViewSetKey);
401 }
402
403 bool SOSRingSetBackupViewset_Internal(SOSRingRef ring, CFSetRef viewSet) {
404 SOSRingAssertStable(ring);
405 return setValueInDict(ring->signedInformation, sBackupViewSetKey, viewSet);
406 }
407
408
409
410 // MARK: Ring PeerIDs
411
412 static inline CFMutableSetRef SOSRingGetPeerIDs(SOSRingRef ring) {
413 SOSRingAssertStable(ring);
414 return (CFMutableSetRef) CFDictionaryGetValue(ring->signedInformation, sPeerIDsKey);
415 }
416
417 bool SOSRingSetPeerIDs(SOSRingRef ring, CFMutableSetRef peers) {
418 SOSRingAssertStable(ring);
419 return setValueInDict(ring->signedInformation, sPeerIDsKey, peers);
420 }
421
422 int SOSRingCountPeerIDs(SOSRingRef ring) {
423 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
424 return (int)CFSetGetCount(peerIDs);
425 }
426
427
428 bool SOSRingHasPeerID(SOSRingRef ring, CFStringRef peerID) {
429 SOSRingAssertStable(ring);
430 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerID);
431 }
432
433 CFMutableSetRef SOSRingCopyPeerIDs(SOSRingRef ring) {
434 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
435 return CFSetCreateMutableCopy(ALLOCATOR, 0, peerIDs);
436 }
437
438 void SOSRingAddAll(SOSRingRef ring, CFSetRef peerInfosOrIDs) {
439 CFSetForEach(peerInfosOrIDs, ^(const void *value) {
440 CFStringRef peerID = value;
441
442 if (isSOSPeerInfo(value))
443 peerID = SOSPeerInfoGetPeerID((SOSPeerInfoRef)value);
444
445 if (isString(peerID))
446 SOSRingAddPeerID(ring, peerID);
447 });
448 }
449
450 bool SOSRingAddPeerID(SOSRingRef ring, CFStringRef peerid) {
451 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
452 CFSetAddValue(peerIDs, peerid);
453 return true;
454 }
455
456 bool SOSRingRemovePeerID(SOSRingRef ring, CFStringRef peerid) {
457 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
458 CFSetRemoveValue(peerIDs, peerid);
459 return true;
460 }
461
462 void SOSRingForEachPeerID(SOSRingRef ring, void (^action)(CFStringRef peerID)) {
463 SOSRingAssertStable(ring);
464 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
465 if(!peerIDs) return;
466 CFSetForEach(peerIDs, ^(const void*value) {
467 CFStringRef peerID = (CFStringRef) value;
468 action(peerID);
469 });
470 }
471
472 // MARK: SOSRing Ops
473
474 SOSRingRef SOSRingCreate_Internal(CFStringRef name, SOSRingType type, CFErrorRef *error) {
475 SOSRingRef r = SOSRingAllocate();
476 SOSGenCountRef gen = SOSGenerationCreate();
477
478 require_action_quiet(name, errout0,
479 SOSCreateError(kSOSErrorNoCircleName, CFSTR("No ring name"), NULL, error));
480 require_action_quiet(SOSRingCheckType(type, error), errout0,
481 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Unknown ring type"), NULL, error));
482 require_action_quiet((r->unSignedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
483 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate unsigned information area"), NULL, error));
484 require_action_quiet((r->signedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
485 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signed information area"), NULL, error));
486 require_action_quiet((r->signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
487 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signature area"), NULL, error));
488 require_action_quiet((r->data = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
489 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate data area"), NULL, error));
490
491 require_action_quiet(SOSRingSetName(r, name), errout,
492 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring name area"), NULL, error));
493 require_action_quiet(SOSRingSetType(r, type), errout,
494 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring type"), NULL, error));
495 require_action_quiet(SOSRingSetVersion(r), errout,
496 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring version"), NULL, error));
497 require_action_quiet(SOSRingSetIdentifier(r), errout,
498 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring identifier"), NULL, error));
499
500 CFMutableSetRef peerIDs = CFSetCreateMutableForSOSPeerIDs();
501 require_action_quiet(SOSRingSetApplicants(r, peerIDs), errout,
502 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate applicant area"), NULL, error));
503 CFReleaseNull(peerIDs);
504
505 CFMutableSetRef rejectedIDs = CFSetCreateMutableForSOSPeerIDs();
506 require_action_quiet(SOSRingSetRejections(r, rejectedIDs), errout,
507 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate rejection area"), NULL, error));
508 CFReleaseNull(rejectedIDs);
509
510 require_action_quiet(SOSRingSetGeneration(r, gen), errout,
511 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate generation count"), NULL, error));
512
513 peerIDs = CFSetCreateMutableForSOSPeerIDs();
514 require_action_quiet(SOSRingSetPeerIDs(r, peerIDs), errout,
515 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate PeerID"), NULL, error));
516 CFReleaseNull(gen);
517 CFReleaseNull(peerIDs);
518
519 return r;
520 errout:
521 CFReleaseNull(r->unSignedInformation);
522 CFReleaseNull(r->signedInformation);
523 CFReleaseNull(r->signatures);
524 CFReleaseNull(r->data);
525 errout0:
526 CFReleaseNull(gen);
527 CFReleaseNull(r);
528 return NULL;
529 }
530
531
532 static void SOSRingDestroy(CFTypeRef aObj) {
533 SOSRingRef c = (SOSRingRef) aObj;
534
535 CFReleaseNull(c->unSignedInformation);
536 CFReleaseNull(c->signedInformation);
537 CFReleaseNull(c->data);
538 CFReleaseNull(c->signatures);
539 }
540
541
542 SOSRingRef SOSRingCopyRing(SOSRingRef original, CFErrorRef *error) {
543 SOSRingRef r = CFTypeAllocate(SOSRing, struct __OpaqueSOSRing, ALLOCATOR);
544
545 assert(original);
546 r->unSignedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->unSignedInformation);
547 r->signedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signedInformation);
548 r->signatures = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signatures);
549 r->data = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->data);
550
551 return r;
552 }
553
554 bool SOSRingIsEmpty_Internal(SOSRingRef ring) {
555 return CFSetGetCount(SOSRingGetPeerIDs(ring)) == 0;
556 }
557
558 bool SOSRingIsOffering_Internal(SOSRingRef ring) {
559 return SOSRingCountPeers(ring) == 1;
560 }
561
562 bool SOSRingResetToEmpty_Internal(SOSRingRef ring, CFErrorRef *error) {
563 SOSGenCountRef gen = NULL;
564 CFSetRemoveAllValues(SOSRingGetApplicants(ring));
565 CFSetRemoveAllValues(SOSRingGetRejections(ring));
566 CFSetRemoveAllValues(SOSRingGetPeerIDs(ring));
567 CFDictionaryRemoveAllValues(ring->signatures);
568 SOSRingSetGeneration(ring, gen = SOSGenerationCreate());
569 CFReleaseNull(gen);
570 return true;
571 }
572
573 // MARK: PeerIDs in Ring
574
575 #if 0
576 static inline bool isHiddenPeer(SOSPeerInfoRef peer) {
577 return SOSPeerInfoIsRetirementTicket(peer) || SOSPeerInfoIsCloudIdentity(peer);
578 }
579 #endif
580
581 int SOSRingCountPeers(SOSRingRef ring) {
582 SOSRingAssertStable(ring);
583 return (int) CFSetGetCount(SOSRingGetPeerIDs(ring));
584 }
585
586
587 bool SOSRingHasPeerWithID(SOSRingRef ring, CFStringRef peerid, CFErrorRef *error) {
588 SOSRingAssertStable(ring);
589 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerid);
590 }
591
592 // MARK: Ring Signatures
593
594
595 static inline CFDictionaryRef SOSRingGetSignatures(SOSRingRef ring) {
596 return ring->signatures;
597 }
598
599 static inline CFDataRef SOSRingGetSignatureForPeerID(SOSRingRef ring, CFStringRef peerID) {
600 if(!ring || !peerID) return NULL;
601 CFDataRef result = NULL;
602 CFTypeRef value = (CFDataRef)CFDictionaryGetValue(SOSRingGetSignatures(ring), peerID);
603 if (isData(value)) result = (CFDataRef) value;
604 return result;
605 }
606
607 static CFDataRef SOSRingCreateHash(const struct ccdigest_info *di, SOSRingRef ring, CFErrorRef *error) {
608 uint8_t hash_result[di->output_size];
609
610 size_t dersize = der_sizeof_plist(ring->signedInformation, error);
611 if(dersize == 0) {
612 return false;
613 }
614 uint8_t der[dersize];
615 der_encode_plist(ring->signedInformation, error, der, der+dersize);
616
617 ccdigest(di, dersize, der, hash_result);
618 return CFDataCreate(NULL, hash_result, di->output_size);
619 }
620
621 static bool SOSRingSetSignature(SOSRingRef ring, SecKeyRef privKey, CFDataRef signature, CFErrorRef *error) {
622 bool result = false;
623 SecKeyRef pubkey = SecKeyCreatePublicFromPrivate(privKey);
624 CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error);
625 require_quiet(pubKeyID, fail);
626 CFDictionarySetValue(ring->signatures, pubKeyID, signature);
627 result = true;
628 fail:
629 CFReleaseSafe(pubkey);
630 CFReleaseSafe(pubKeyID);
631 return result;
632 }
633
634 static bool SOSRingRemoveSignatures(SOSRingRef ring, CFErrorRef *error) {
635 CFDictionaryRemoveAllValues(ring->signatures);
636 return true;
637 }
638
639 static CFDataRef SOSHashSign(SecKeyRef privKey, CFDataRef hash, CFErrorRef *error) {
640 size_t siglen = SecKeyGetSize(privKey, kSecKeySignatureSize)+16;
641 uint8_t sig[siglen];
642 OSStatus stat = SecKeyRawSign(privKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash), sig, &siglen);
643 if(stat) {
644 return NULL;
645 }
646 return CFDataCreate(NULL, sig, siglen);
647 }
648
649 static bool SOSRingSign(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
650 if (!ring || !privKey) {
651 SOSCreateError(kSOSErrorBadSignature, CFSTR("SOSRingSign Lacking ring or private key"),
652 (error != NULL) ? *error : NULL, error);
653 return false;
654 }
655 const struct ccdigest_info *di = ccsha256_di();
656 CFDataRef hash = SOSRingCreateHash(di, ring, error);
657 CFDataRef signature = SOSHashSign(privKey, hash, error);
658 SOSRingSetSignature(ring, privKey, signature, error);
659 CFRelease(signature);
660 CFReleaseNull(hash);
661 return true;
662 }
663
664 bool SOSRingVerifySignatureExists(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
665 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
666 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
667 CFReleaseNull(pubKeyID);
668 return NULL != signature;
669 }
670
671 bool SOSRingVerify(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
672 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
673 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
674 CFReleaseNull(pubKeyID);
675 if(!signature) return false;
676 CFDataRef hash = SOSRingCreateHash(ccsha256_di(), ring, error);
677 bool success = SecKeyRawVerify(pubKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash),
678 CFDataGetBytePtr(signature), CFDataGetLength(signature)) == errSecSuccess;
679 CFReleaseNull(hash);
680 return success;
681 }
682
683 bool SOSRingVerifyPeerSigned(SOSRingRef ring, SOSPeerInfoRef peer, CFErrorRef *error) {
684 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(peer);
685 bool result = SOSRingVerify(ring, pubkey, error);
686 CFReleaseSafe(pubkey);
687 return result;
688 }
689
690 static bool SOSRingEnsureRingConsistency(SOSRingRef ring, CFErrorRef *error) {
691 secnotice("Development", "SOSRingEnsureRingConsistency requires ring membership and generation count consistency check", NULL);
692 return true;
693 }
694
695 bool SOSRingGenerationSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
696 if(!privKey || !ring) return false;
697 bool retval = false;
698 SOSRingGenerationIncrement(ring);
699 require_quiet(SOSRingEnsureRingConsistency(ring, error), fail);
700 require_quiet(SOSRingRemoveSignatures(ring, error), fail);
701 require_quiet(SOSRingSign(ring, privKey, error), fail);
702 retval = true;
703 fail:
704 return retval;
705 }
706
707 // MARK: Concordance
708
709 bool SOSRingConcordanceSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
710 if(!privKey || !ring) return false;
711 bool retval = false;
712 require_quiet(SOSRingSign(ring, privKey, error), fail);
713 retval = true;
714 fail:
715 return retval;
716 }
717
718
719
720 // MARK: Debugging
721
722 static inline void CFSetForEachPeerID(CFSetRef set, void (^operation)(CFStringRef peerID)) {
723 CFSetForEach(set, ^(const void *value) {
724 CFStringRef peerID = (CFStringRef) value;
725 operation(peerID);
726 });
727 }
728
729 static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) {
730 CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0);
731
732 __block bool addSeparator = false;
733
734 CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
735 if (addSeparator) {
736 CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
737 }
738 CFStringAppend(result, peerID);
739
740 addSeparator = true;
741 });
742
743 return result;
744 }
745
746 CFDictionaryRef SOSRingPeerIDList(SOSRingRef ring) {
747 CFStringRef peerIDS = CreateCommaSeparatedPeerIDs(SOSRingGetPeerIDs(ring));
748 CFStringRef applicantIDs = CreateCommaSeparatedPeerIDs(SOSRingGetApplicants(ring));
749 CFStringRef rejectIDs = CreateCommaSeparatedPeerIDs(SOSRingGetRejections(ring));
750 CFDictionaryRef list = CFDictionaryCreateForCFTypes(ALLOCATOR,
751 CFSTR("MEMBER"), peerIDS,
752 CFSTR("APPLICANTS"), applicantIDs,
753 CFSTR("REJECTS"), rejectIDs,
754 NULL);
755
756 CFReleaseNull(peerIDS);
757 CFReleaseNull(applicantIDs);
758 CFReleaseNull(rejectIDs);
759 return list;
760 }
761
762 CFStringRef SOSRingSignerList(SOSRingRef ring) {
763 __block bool addSeparator = false;
764 CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0);
765 CFDictionaryForEach(ring->signatures, ^(const void *key, const void *value) {
766 CFStringRef peerID = (CFStringRef) key;
767 if (addSeparator)
768 CFStringAppendCString(signers, ", ", kCFStringEncodingUTF8);
769 CFStringAppend(signers, peerID);
770 addSeparator = true;
771 });
772 return signers;
773 }
774
775 static CFStringRef SOSRingCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOpts) {
776 SOSRingRef ring = (SOSRingRef) aObj;
777
778 SOSRingAssertStable(ring);
779
780 CFDictionaryRef peers = SOSRingPeerIDList(ring);
781 CFStringRef signers = SOSRingSignerList(ring);
782
783 CFDataRef payload = SOSRingGetPayload(ring, NULL);
784
785 CFStringRef gcString = SOSGenerationCountCopyDescription(SOSRingGetGeneration(ring));
786
787 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
788
789 CFStringAppendFormat(description, formatOpts, CFSTR("<SOSRing@%p: '%@', Version %u, "), ring, SOSRingGetName(ring), SOSRingGetVersion(ring));
790 CFStringAppendFormat(description, formatOpts, CFSTR("UUID: %@, "), SOSRingGetIdentifier(ring));
791 SOSGenerationCountWithDescription(SOSRingGetGeneration(ring), ^(CFStringRef gcString) {
792 CFStringAppendFormat(description, formatOpts, CFSTR("Gen: %@, "), gcString);
793 });
794 CFStringAppendFormat(description, formatOpts, CFSTR("Mod: %@, "), SOSRingGetLastModifier(ring));
795
796 CFStringAppendFormat(description, formatOpts, CFSTR("D: %ld "), payload ? CFDataGetLength(payload) : 0);
797
798 SOSBackupSliceKeyBagRef payloadAsBSKB = SOSRingCopyBackupSliceKeyBag(ring, NULL);
799
800 if (payloadAsBSKB) {
801 CFStringAppendFormat(description, formatOpts, CFSTR("%@ "), payloadAsBSKB);
802 }
803
804 CFReleaseSafe(payloadAsBSKB);
805
806 CFStringAppendFormat(description, formatOpts, CFSTR("P: [%@], "), CFDictionaryGetValue(peers, CFSTR("MEMBER")));
807 CFStringAppendFormat(description, formatOpts, CFSTR("A: [%@], "), CFDictionaryGetValue(peers, CFSTR("APPLICANTS")));
808 CFStringAppendFormat(description, formatOpts, CFSTR("R: [%@], "), CFDictionaryGetValue(peers, CFSTR("REJECTS")));
809 CFStringAppendFormat(description, formatOpts, CFSTR("S: [%@]>"), signers);
810
811 CFReleaseNull(gcString);
812 CFReleaseNull(peers);
813 CFReleaseNull(signers);
814
815 return description;
816 }
817
818 //
819 // Peer Retirement
820 //
821
822 #define SIGLEN 128
823 #if 0
824 static CFDataRef sosSignHash(SecKeyRef privkey, const struct ccdigest_info *di, uint8_t *hbuf) {
825 OSStatus stat;
826 size_t siglen = SIGLEN;
827 uint8_t sig[siglen];
828 if((stat = SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen)) != 0) {
829 return NULL;
830 }
831 return CFDataCreate(NULL, sig, (CFIndex)siglen);
832 }
833 #endif
834 #if 0
835 static void WithBufferSpace(size_t space, void (^action)(uint8_t *buffer, size_t length)) {
836 if (space == 0) {
837 action(NULL, space);
838 } else if (space <= 2048) {
839 uint8_t buffer[space];
840
841 action(buffer, space);
842 } else {
843 uint8_t* buffer = malloc(space);
844
845 action(buffer, space);
846
847 free(buffer);
848 }
849 }
850
851 static CFDataRef CFDictionaryHashCreate(CFDictionaryRef dict, CFErrorRef *error) {
852
853 __block CFDataRef result = NULL;
854
855 require_quiet(dict, errOut);
856
857 WithBufferSpace(der_sizeof_dictionary(dict, error), ^(uint8_t *der, size_t len) {
858 if (len > 0) {
859 const struct ccdigest_info *di = ccsha256_di();
860 uint8_t hash_result[di->output_size];
861 der_encode_dictionary(dict, error, der, der+len);
862
863 ccdigest(di, len, der, hash_result);
864 result = CFDataCreate(ALLOCATOR, hash_result, di->output_size);
865 }
866 });
867
868 errOut:
869 return NULL;
870 }
871 #endif
872 /*
873 CFDictionary:
874 signatures: CFDictionary of key = hash(pubkey), value = signature(privkey, (DER(payload))
875 payload: CFDictionary passed in
876
877
878 */
879 #if 0
880 static CFStringRef sPayload = CFSTR("payload");
881 static CFStringRef sSignature = CFSTR("signature");
882
883 static bool SOSCFSignedDictionarySetSignature(SecKeyRef priv, CFDictionaryRef sd, CFErrorRef *error) {
884 CFDictionaryRef payload = CFDictionaryGetValue(sd, sPayload);
885 CFMutableDictionaryRef signatures = (CFMutableDictionaryRef) CFDictionaryGetValue(sd, sSignature);
886 CFDataRef hash = CFDictionaryHashCreate(payload, error);
887 CFDataRef signature = SOSHashSign(priv, hash, error);
888 CFReleaseNull(hash);
889 CFStringRef pubhash = SOSCopyIDOfKey(priv, error);
890 require_quiet(signature && pubhash, errOut);
891 CFDictionaryAddValue(signatures, pubhash, signature);
892 return true;
893 errOut:
894 return false;
895 }
896 #endif
897 #if 0
898 static CFDictionaryRef SOSCFSignedDictionaryCreate(SecKeyRef priv, CFDictionaryRef payload, CFErrorRef *error) {
899 CFMutableDictionaryRef signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
900 CFMutableDictionaryRef retval = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
901 require_quiet(signatures && retval, errOut);
902
903 CFDictionaryAddValue(retval, sSignature, signatures);
904 CFDictionaryAddValue(retval, sPayload, payload);
905 SOSCFSignedDictionarySetSignature(priv, retval, error);
906 return retval;
907 errOut:
908 CFReleaseNull(signatures);
909 CFReleaseNull(retval);
910 return NULL;
911 }
912 #endif
913
914 #if 0
915 CFDictionaryRef SOSRingCreateRetirementTicket(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
916 CFDictionaryRef retval = NULL;
917 CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpi));
918 SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(fpi, error);
919 CFDataRef resignationDate = SOSDateCreate();
920 GENCOUNT!!!
921
922 CFDataRef sig = SOSDERAndSignStuff(priv, keys, values, 2, error);
923 retval = CFDictionaryCreate(ALLOCATOR, <#const void **keys#>, <#const void **values#>, <#CFIndex numValues#>, <#const CFDictionaryKeyCallBacks *keyCallBacks#>, <#const CFDictionaryValueCallBacks *valueCallBacks#>)
924 return pi;
925
926 exit_stage_right:
927 CFReleaseNull(priv);
928 CFReleaseNull(resignationDate);
929 return retval;
930 }
931 #endif