]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSRingUtils.c
Security-57336.10.29.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 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 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 (CFSetRef) CFDictionaryGetValue(ring->signedInformation, sBackupViewSetKey);
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) CFDictionaryGetValue(ring->signedInformation, sPeerIDsKey);
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 SOSHashSign(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 = SOSHashSign(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 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(peer);
692 bool result = SOSRingVerify(ring, pubkey, error);
693 CFReleaseSafe(pubkey);
694 return result;
695 }
696
697 static bool SOSRingEnsureRingConsistency(SOSRingRef ring, CFErrorRef *error) {
698 secnotice("Development", "SOSRingEnsureRingConsistency requires ring membership and generation count consistency check", NULL);
699 return true;
700 }
701
702 bool SOSRingGenerationSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
703 if(!privKey || !ring) return false;
704 bool retval = false;
705 SOSRingGenerationIncrement(ring);
706 require_quiet(SOSRingEnsureRingConsistency(ring, error), fail);
707 require_quiet(SOSRingRemoveSignatures(ring, error), fail);
708 require_quiet(SOSRingSign(ring, privKey, error), fail);
709 retval = true;
710 fail:
711 return retval;
712 }
713
714 // MARK: Concordance
715
716 bool SOSRingConcordanceSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
717 if(!privKey || !ring) return false;
718 bool retval = false;
719 require_quiet(SOSRingSign(ring, privKey, error), fail);
720 retval = true;
721 fail:
722 return retval;
723 }
724
725
726
727 // MARK: Debugging
728
729 static inline void CFSetForEachPeerID(CFSetRef set, void (^operation)(CFStringRef peerID)) {
730 CFSetForEach(set, ^(const void *value) {
731 CFStringRef peerID = (CFStringRef) value;
732 operation(peerID);
733 });
734 }
735
736 static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) {
737 CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0);
738
739 __block bool addSeparator = false;
740
741 CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
742 if (addSeparator) {
743 CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
744 }
745 CFStringAppend(result, peerID);
746
747 addSeparator = true;
748 });
749
750 return result;
751 }
752
753 CFDictionaryRef SOSRingCopyPeerIDList(SOSRingRef ring) {
754 CFStringRef peerIDS = CreateCommaSeparatedPeerIDs(SOSRingGetPeerIDs(ring));
755 CFStringRef applicantIDs = CreateCommaSeparatedPeerIDs(SOSRingGetApplicants(ring));
756 CFStringRef rejectIDs = CreateCommaSeparatedPeerIDs(SOSRingGetRejections(ring));
757 CFDictionaryRef list = CFDictionaryCreateForCFTypes(ALLOCATOR,
758 CFSTR("MEMBER"), peerIDS,
759 CFSTR("APPLICANTS"), applicantIDs,
760 CFSTR("REJECTS"), rejectIDs,
761 NULL);
762
763 CFReleaseNull(peerIDS);
764 CFReleaseNull(applicantIDs);
765 CFReleaseNull(rejectIDs);
766 return list;
767 }
768
769 CFStringRef SOSRingCopySignerList(SOSRingRef ring) {
770 __block bool addSeparator = false;
771 CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0);
772 CFDictionaryForEach(ring->signatures, ^(const void *key, const void *value) {
773 CFStringRef peerID = (CFStringRef) key;
774 if (addSeparator)
775 CFStringAppendCString(signers, ", ", kCFStringEncodingUTF8);
776 CFStringAppend(signers, peerID);
777 addSeparator = true;
778 });
779 return signers;
780 }
781
782 static CFStringRef SOSRingCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOpts) {
783 SOSRingRef ring = (SOSRingRef) aObj;
784
785 SOSRingAssertStable(ring);
786
787 CFDictionaryRef peers = SOSRingCopyPeerIDList(ring);
788 CFStringRef signers = SOSRingCopySignerList(ring);
789
790 CFDataRef payload = SOSRingGetPayload(ring, NULL);
791
792 CFStringRef gcString = SOSGenerationCountCopyDescription(SOSRingGetGeneration(ring));
793
794 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
795
796 CFStringAppendFormat(description, formatOpts, CFSTR("<SOSRing@%p: '%@', Version %u, "), ring, SOSRingGetName(ring), SOSRingGetVersion(ring));
797 CFStringAppendFormat(description, formatOpts, CFSTR("UUID: %@, "), SOSRingGetIdentifier(ring));
798 SOSGenerationCountWithDescription(SOSRingGetGeneration(ring), ^(CFStringRef gcString) {
799 CFStringAppendFormat(description, formatOpts, CFSTR("Gen: %@, "), gcString);
800 });
801 CFStringAppendFormat(description, formatOpts, CFSTR("Mod: %@, "), SOSRingGetLastModifier(ring));
802
803 CFStringAppendFormat(description, formatOpts, CFSTR("D: %ld "), payload ? CFDataGetLength(payload) : 0);
804
805 SOSBackupSliceKeyBagRef payloadAsBSKB = SOSRingCopyBackupSliceKeyBag(ring, NULL);
806
807 if (payloadAsBSKB) {
808 CFStringAppendFormat(description, formatOpts, CFSTR("%@ "), payloadAsBSKB);
809 }
810
811 CFReleaseSafe(payloadAsBSKB);
812
813 CFStringAppendFormat(description, formatOpts, CFSTR("P: [%@], "), CFDictionaryGetValue(peers, CFSTR("MEMBER")));
814 CFStringAppendFormat(description, formatOpts, CFSTR("A: [%@], "), CFDictionaryGetValue(peers, CFSTR("APPLICANTS")));
815 CFStringAppendFormat(description, formatOpts, CFSTR("R: [%@], "), CFDictionaryGetValue(peers, CFSTR("REJECTS")));
816 CFStringAppendFormat(description, formatOpts, CFSTR("S: [%@]>"), signers);
817
818 CFReleaseNull(gcString);
819 CFReleaseNull(peers);
820 CFReleaseNull(signers);
821 CFReleaseNull(peers);
822
823 return description;
824 }
825
826 //
827 // Peer Retirement
828 //
829
830 #define SIGLEN 128
831 #if 0
832 static CFDataRef sosSignHash(SecKeyRef privkey, const struct ccdigest_info *di, uint8_t *hbuf) {
833 OSStatus stat;
834 size_t siglen = SIGLEN;
835 uint8_t sig[siglen];
836 if((stat = SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen)) != 0) {
837 return NULL;
838 }
839 return CFDataCreate(NULL, sig, (CFIndex)siglen);
840 }
841 #endif
842 #if 0
843 static void WithBufferSpace(size_t space, void (^action)(uint8_t *buffer, size_t length)) {
844 if (space == 0) {
845 action(NULL, space);
846 } else if (space <= 2048) {
847 uint8_t buffer[space];
848
849 action(buffer, space);
850 } else {
851 uint8_t* buffer = malloc(space);
852
853 action(buffer, space);
854
855 free(buffer);
856 }
857 }
858
859 static CFDataRef CFDictionaryHashCreate(CFDictionaryRef dict, CFErrorRef *error) {
860
861 __block CFDataRef result = NULL;
862
863 require_quiet(dict, errOut);
864
865 WithBufferSpace(der_sizeof_dictionary(dict, error), ^(uint8_t *der, size_t len) {
866 if (len > 0) {
867 const struct ccdigest_info *di = ccsha256_di();
868 uint8_t hash_result[di->output_size];
869 der_encode_dictionary(dict, error, der, der+len);
870
871 ccdigest(di, len, der, hash_result);
872 result = CFDataCreate(ALLOCATOR, hash_result, di->output_size);
873 }
874 });
875
876 errOut:
877 return NULL;
878 }
879 #endif
880 /*
881 CFDictionary:
882 signatures: CFDictionary of key = hash(pubkey), value = signature(privkey, (DER(payload))
883 payload: CFDictionary passed in
884
885
886 */
887 #if 0
888 static CFStringRef sPayload = CFSTR("payload");
889 static CFStringRef sSignature = CFSTR("signature");
890
891 static bool SOSCFSignedDictionarySetSignature(SecKeyRef priv, CFDictionaryRef sd, CFErrorRef *error) {
892 CFDictionaryRef payload = CFDictionaryGetValue(sd, sPayload);
893 CFMutableDictionaryRef signatures = (CFMutableDictionaryRef) CFDictionaryGetValue(sd, sSignature);
894 CFDataRef hash = CFDictionaryHashCreate(payload, error);
895 CFDataRef signature = SOSHashSign(priv, hash, error);
896 CFReleaseNull(hash);
897 CFStringRef pubhash = SOSCopyIDOfKey(priv, error);
898 require_quiet(signature && pubhash, errOut);
899 CFDictionaryAddValue(signatures, pubhash, signature);
900 return true;
901 errOut:
902 return false;
903 }
904 #endif
905 #if 0
906 static CFDictionaryRef SOSCFSignedDictionaryCreate(SecKeyRef priv, CFDictionaryRef payload, CFErrorRef *error) {
907 CFMutableDictionaryRef signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
908 CFMutableDictionaryRef retval = CFDictionaryCreateMutableForCFTypes(ALLOCATOR);
909 require_quiet(signatures && retval, errOut);
910
911 CFDictionaryAddValue(retval, sSignature, signatures);
912 CFDictionaryAddValue(retval, sPayload, payload);
913 SOSCFSignedDictionarySetSignature(priv, retval, error);
914 return retval;
915 errOut:
916 CFReleaseNull(signatures);
917 CFReleaseNull(retval);
918 return NULL;
919 }
920 #endif
921
922 #if 0
923 CFDictionaryRef SOSRingCreateRetirementTicket(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
924 CFDictionaryRef retval = NULL;
925 CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpi));
926 SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(fpi, error);
927 CFDataRef resignationDate = SOSDateCreate();
928 GENCOUNT!!!
929
930 CFDataRef sig = SOSDERAndSignStuff(priv, keys, values, 2, error);
931 retval = CFDictionaryCreate(ALLOCATOR, <#const void **keys#>, <#const void **values#>, <#CFIndex numValues#>, <#const CFDictionaryKeyCallBacks *keyCallBacks#>, <#const CFDictionaryValueCallBacks *valueCallBacks#>)
932 return pi;
933
934 exit_stage_right:
935 CFReleaseNull(priv);
936 CFReleaseNull(resignationDate);
937 return retval;
938 }
939 #endif