]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSRingUtils.c
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / 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 "keychain/SecureObjectSync/SOSInternal.h"
32 #include "keychain/SecureObjectSync/SOSPeer.h"
33 #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
34 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
35 #include "keychain/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 <utilities/simulatecrash_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 static bool setValueInDict(CFMutableDictionaryRef thedict, CFStringRef key, CFTypeRef value) {
86 if(!value) return false;
87 CFDictionarySetValue(thedict, key, value);
88 return true;
89 }
90
91 static CFMutableSetRef CFSetCreateMutableForSOSPeerIDs(void) {
92 return CFSetCreateMutable(ALLOCATOR, 0, &kCFTypeSetCallBacks);
93 }
94
95
96 static inline
97 SOSRingRef SOSRingConvertAndAssertStable(CFTypeRef ringAsType) {
98 if (CFGetTypeID(ringAsType) != SOSRingGetTypeID())
99 return NULL;
100
101 SOSRingRef ring = (SOSRingRef) ringAsType;
102
103 SOSRingAssertStable(ring);
104
105 return ring;
106 }
107
108 // MARK: Ring Name
109
110 CFStringRef SOSRingGetName(SOSRingRef ring) {
111 assert(ring);
112 assert(ring->signedInformation);
113 return asString(CFDictionaryGetValue(ring->signedInformation, sNameKey), NULL);
114 }
115
116 const char *SOSRingGetNameC(SOSRingRef ring) {
117 CFStringRef name = asString(SOSRingGetName(ring), NULL);
118 if (!name)
119 return strdup("");
120 return CFStringToCString(name);
121 }
122
123 static inline bool SOSRingSetName(SOSRingRef ring, CFStringRef name) {
124 assert(ring);
125 assert(ring->signedInformation);
126 return setValueInDict(ring->signedInformation, sNameKey, name);
127 }
128
129 // MARK: Ring Type
130
131 static bool SOSRingCheckType(SOSRingType type, CFErrorRef *error) {
132 if(type < kSOSRingTypeCount) return true;
133 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Bad Ring Type Specification"), (error != NULL) ? *error : NULL, error);
134 return false;
135 }
136
137 uint32_t SOSRingGetType(SOSRingRef ring) {
138 uint32_t retval = kSOSRingTypeError; // Error return
139 SOSRingAssertStable(ring);
140 if(!ring->signedInformation) return retval;
141 CFNumberRef ringtype = (CFNumberRef) CFDictionaryGetValue(ring->signedInformation, sTypeKey);
142 CFNumberGetValue(ringtype, kCFNumberSInt32Type, &retval);
143 return retval;
144 }
145
146 static inline bool SOSRingSetType(SOSRingRef ring, uint32_t ringtype) {
147 bool retval = false;
148 CFNumberRef cfrtype = NULL;
149 SOSRingAssertStable(ring);
150 require_action_quiet(SOSRingCheckType(ringtype, NULL), errOut, secnotice("ring", "Bad ring type specification"));
151 cfrtype = CFNumberCreate(ALLOCATOR, kCFNumberSInt32Type, &ringtype);
152 retval = setValueInDict(ring->signedInformation, sTypeKey, cfrtype);
153 errOut:
154 CFReleaseNull(cfrtype);
155 return retval;
156 }
157
158 // MARK: Version
159
160 uint32_t SOSRingGetVersion(SOSRingRef ring) {
161 uint32_t version = 0;
162 assert(ring);
163 assert(ring->signedInformation);
164 CFNumberRef cfversion = CFDictionaryGetValue(ring->signedInformation, sRingVersionKey);
165 require_action_quiet(cfversion, errOut, secnotice("ring", "Could not create version number"));
166 CFNumberGetValue(cfversion, kCFNumberSInt32Type, &version);
167 errOut:
168 return version;
169 }
170
171 static inline bool SOSRingSetVersion(SOSRingRef ring) {
172 assert(ring);
173 assert(ring->signedInformation);
174 int32_t thisversion = RINGVERSION;
175 CFNumberRef version = CFNumberCreate(ALLOCATOR, kCFNumberSInt32Type, &thisversion);
176 require_action_quiet(version, errOut, secnotice("ring", "Could not create version number"));
177 CFDictionarySetValue(ring->signedInformation, sRingVersionKey, version);
178 CFReleaseNull(version);
179 return true;
180 errOut:
181 return false;
182 }
183
184 // MARK: Identifier
185
186 CFStringRef SOSRingGetIdentifier(SOSRingRef ring) {
187 assert(ring);
188 assert(ring->signedInformation);
189 return CFDictionaryGetValue(ring->signedInformation, sIdentifierKey);
190 }
191
192 static inline bool SOSRingSetIdentifier(SOSRingRef ring) {
193 assert(ring);
194 assert(ring->signedInformation);
195 bool retval = false;
196 CFStringRef identifier = NULL;
197 CFUUIDRef uuid = CFUUIDCreate(ALLOCATOR);
198 require_action_quiet(uuid, errOut, secnotice("ring", "Could not create ring identifier"));
199 identifier = CFUUIDCreateString(ALLOCATOR, uuid);
200 CFDictionarySetValue(ring->signedInformation, sIdentifierKey, identifier);
201 retval = true;
202 errOut:
203 CFReleaseNull(uuid);
204 CFReleaseNull(identifier);
205 return retval;
206 }
207
208 // MARK: Ring Identity
209
210 bool SOSRingIsSame(SOSRingRef ring1, SOSRingRef ring2) {
211 CFStringRef name1 = SOSRingGetName(ring1);
212 CFStringRef name2 = SOSRingGetName(ring2);
213 require_action_quiet(name1 && name2, errOut, secnotice("ring", "Cannot get both names to consider rings the same"));
214 if(CFEqualSafe(name1, name2) != true) return false;
215
216 uint32_t type1 = SOSRingGetType(ring1);
217 uint32_t type2 = SOSRingGetVersion(ring2);
218 require_action_quiet(type1 && type2, errOut, secnotice("ring", "Cannot get both types to consider rings the same"));
219 if(type1 != type2) return false;
220
221 CFStringRef identifier1 = SOSRingGetIdentifier(ring1);
222 CFStringRef identifier2 = SOSRingGetIdentifier(ring2);
223 require_action_quiet(identifier1 && identifier2, errOut, secnotice("ring", "Cannot get both identifiers to consider rings the same"));
224 if(CFEqualSafe(identifier1, identifier2) != true) return false;
225
226 return true;
227 errOut:
228 return false;
229
230 }
231
232 static Boolean SOSRingCompare(CFTypeRef lhs, CFTypeRef rhs) {
233 if (CFGetTypeID(lhs) != SOSRingGetTypeID()
234 || CFGetTypeID(rhs) != SOSRingGetTypeID())
235 return false;
236
237 SOSRingRef left = SOSRingConvertAndAssertStable(lhs);
238 SOSRingRef right = SOSRingConvertAndAssertStable(rhs);
239
240 return NULL != left && NULL != right
241 && CFEqualSafe(left->unSignedInformation, right->unSignedInformation)
242 && CFEqualSafe(left->signedInformation, right->signedInformation)
243 && CFEqualSafe(left->data, right->data)
244 && CFEqualSafe(left->signatures, right->signatures);
245 }
246
247
248 // MARK: Ring Generation Count
249
250 SOSGenCountRef SOSRingGetGeneration(SOSRingRef ring) {
251 assert(ring);
252 assert(ring->signedInformation);
253 return CFDictionaryGetValue(ring->signedInformation, sGenerationKey);
254 }
255
256 static inline bool SOSRingSetGeneration(SOSRingRef ring, SOSGenCountRef gen) {
257 assert(ring);
258 assert(ring->signedInformation);
259 return setValueInDict(ring->signedInformation, sGenerationKey, gen);
260 }
261
262 void SOSRingGenerationIncrement(SOSRingRef ring) {
263 SOSGenCountRef gen = SOSRingGetGeneration(ring);
264 SOSGenCountRef newgen = SOSGenerationIncrementAndCreate(gen);
265 SOSRingSetGeneration(ring, newgen);
266 CFReleaseNull(newgen);
267 }
268
269 bool SOSRingIsOlderGeneration(SOSRingRef olderRing, SOSRingRef newerRing) {
270 SOSGenCountRef old = SOSRingGetGeneration(olderRing);
271 SOSGenCountRef new = SOSRingGetGeneration(newerRing);
272 return SOSGenerationIsOlder(old, new);
273 }
274
275 void SOSRingGenerationCreateWithBaseline(SOSRingRef newring, SOSRingRef baseline) {
276 if(!newring) return;
277 SOSGenCountRef gen = SOSGenerationCreateWithBaseline(SOSRingGetGeneration(baseline));
278 SOSRingSetGeneration(newring, gen);
279 CFReleaseNull(gen);
280 }
281
282 // MARK: Last Modifier
283 CFStringRef SOSRingGetLastModifier(SOSRingRef ring) {
284 assert(ring);
285 assert(ring->unSignedInformation);
286 return CFDictionaryGetValue(ring->unSignedInformation, sLastPeerToModifyKey);
287 }
288
289 bool SOSRingSetLastModifier(SOSRingRef ring, CFStringRef peerID) {
290 assert(ring);
291 assert(ring->unSignedInformation);
292 return setValueInDict(ring->unSignedInformation, sLastPeerToModifyKey, peerID);
293 }
294
295
296 // MARK: Ring Applicants
297
298 CFMutableSetRef SOSRingGetApplicants(SOSRingRef ring) {
299 SOSRingAssertStable(ring);
300 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sApplicantsKey);
301 }
302
303 bool SOSRingSetApplicants(SOSRingRef ring, CFMutableSetRef applicants) {
304 SOSRingAssertStable(ring);
305 return setValueInDict(ring->unSignedInformation, sApplicantsKey, applicants);
306 }
307
308 int SOSRingCountApplicants(SOSRingRef ring) {
309 SOSRingAssertStable(ring);
310 return (int)CFSetGetCount(SOSRingGetApplicants(ring));
311 }
312
313 bool SOSRingHasApplicant(SOSRingRef ring, CFStringRef peerID) {
314 SOSRingAssertStable(ring);
315 return CFSetContainsValue(SOSRingGetApplicants(ring), peerID);
316 }
317
318 CFMutableSetRef SOSRingCopyApplicants(SOSRingRef ring) {
319 SOSRingAssertStable(ring);
320 CFSetRef applicants = SOSRingGetApplicants(ring);
321 return CFSetCreateMutableCopy(ALLOCATOR, 0, applicants);
322 }
323
324 bool SOSRingAddApplicant(SOSRingRef ring, CFStringRef peerid) {
325 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
326 CFSetAddValue(applicants, peerid);
327 return true;
328 }
329
330 bool SOSRingRemoveApplicant(SOSRingRef ring, CFStringRef peerid) {
331 CFMutableSetRef applicants = SOSRingGetApplicants(ring);
332 CFSetRemoveValue(applicants, peerid);
333 return true;
334 }
335
336 // MARK: Ring Rejections
337
338 static inline CFMutableSetRef SOSRingGetRejections(SOSRingRef ring) {
339 SOSRingAssertStable(ring);
340 return (CFMutableSetRef) CFDictionaryGetValue(ring->unSignedInformation, sRejectionsKey);
341 }
342
343 static inline bool SOSRingSetRejections(SOSRingRef ring, CFMutableSetRef rejections) {
344 SOSRingAssertStable(ring);
345 return setValueInDict(ring->unSignedInformation, sRejectionsKey, rejections);
346 }
347
348 int SOSRingCountRejections(SOSRingRef ring) {
349 CFSetRef rejects = SOSRingGetRejections(ring);
350 return (int)CFSetGetCount(rejects);
351 }
352
353 bool SOSRingHasRejection(SOSRingRef ring, CFStringRef peerID) {
354 SOSRingAssertStable(ring);
355 return CFSetContainsValue(SOSRingGetRejections(ring), peerID);
356 }
357
358 CFMutableSetRef SOSRingCopyRejections(SOSRingRef ring) {
359 CFSetRef rejects = SOSRingGetRejections(ring);
360 return CFSetCreateMutableCopy(ALLOCATOR, 0, rejects);
361 }
362
363
364 bool SOSRingAddRejection(SOSRingRef ring, CFStringRef peerid) {
365 CFMutableSetRef rejects = SOSRingGetRejections(ring);
366 CFSetAddValue(rejects, peerid);
367 return true;
368 }
369
370 bool SOSRingRemoveRejection(SOSRingRef ring, CFStringRef peerid) {
371 CFMutableSetRef rejects = SOSRingGetRejections(ring);
372 CFSetRemoveValue(rejects, peerid);
373 return true;
374 }
375
376 // MARK: Ring Payload
377
378 CFDataRef SOSRingGetPayload_Internal(SOSRingRef ring) {
379 SOSRingAssertStable(ring);
380 return (CFDataRef) CFDictionaryGetValue(ring->signedInformation, sPayloadKey);
381 }
382
383 bool SOSRingSetPayload_Internal(SOSRingRef ring, CFDataRef payload) {
384 SOSRingAssertStable(ring);
385 return setValueInDict(ring->signedInformation, sPayloadKey, payload);
386 }
387
388 // MARK: Ring Backup Viewset
389
390
391 CFSetRef SOSRingGetBackupViewset_Internal(SOSRingRef ring) {
392 SOSRingAssertStable(ring);
393 return asSet(CFDictionaryGetValue(ring->signedInformation, sBackupViewSetKey), NULL);
394 }
395
396 bool SOSRingSetBackupViewset_Internal(SOSRingRef ring, CFSetRef viewSet) {
397 SOSRingAssertStable(ring);
398 return setValueInDict(ring->signedInformation, sBackupViewSetKey, viewSet);
399 }
400
401
402
403 // MARK: Ring PeerIDs
404
405 static inline CFMutableSetRef SOSRingGetPeerIDs(SOSRingRef ring) {
406 SOSRingAssertStable(ring);
407 return (CFMutableSetRef) asSet(CFDictionaryGetValue(ring->signedInformation, sPeerIDsKey), NULL);
408 }
409
410 bool SOSRingSetPeerIDs(SOSRingRef ring, CFMutableSetRef peers) {
411 SOSRingAssertStable(ring);
412 return setValueInDict(ring->signedInformation, sPeerIDsKey, peers);
413 }
414
415 int SOSRingCountPeerIDs(SOSRingRef ring) {
416 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
417 return (int)CFSetGetCount(peerIDs);
418 }
419
420
421 bool SOSRingHasPeerID(SOSRingRef ring, CFStringRef peerID) {
422 SOSRingAssertStable(ring);
423 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerID);
424 }
425
426 CFMutableSetRef SOSRingCopyPeerIDs(SOSRingRef ring) {
427 CFSetRef peerIDs = SOSRingGetPeerIDs(ring);
428 return CFSetCreateMutableCopy(ALLOCATOR, 0, peerIDs);
429 }
430
431 void SOSRingAddAll(SOSRingRef ring, CFSetRef peerInfosOrIDs) {
432 CFSetForEach(peerInfosOrIDs, ^(const void *value) {
433 CFStringRef peerID = value;
434
435 if (isSOSPeerInfo(value))
436 peerID = SOSPeerInfoGetPeerID((SOSPeerInfoRef)value);
437
438 if (isString(peerID))
439 SOSRingAddPeerID(ring, peerID);
440 });
441 }
442
443 bool SOSRingAddPeerID(SOSRingRef ring, CFStringRef peerid) {
444 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
445 CFSetAddValue(peerIDs, peerid);
446 return true;
447 }
448
449 bool SOSRingRemovePeerID(SOSRingRef ring, CFStringRef peerid) {
450 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
451 CFSetRemoveValue(peerIDs, peerid);
452 return true;
453 }
454
455 void SOSRingForEachPeerID(SOSRingRef ring, void (^action)(CFStringRef peerID)) {
456 SOSRingAssertStable(ring);
457 CFMutableSetRef peerIDs = SOSRingGetPeerIDs(ring);
458 if(!peerIDs) return;
459 CFSetForEach(peerIDs, ^(const void*value) {
460 CFStringRef peerID = (CFStringRef) value;
461 action(peerID);
462 });
463 }
464
465 // MARK: SOSRing Ops
466
467 SOSRingRef SOSRingCreate_Internal(CFStringRef name, SOSRingType type, CFErrorRef *error) {
468 SOSRingRef r = SOSRingAllocate();
469 SOSGenCountRef gen = SOSGenerationCreate();
470
471 require_action_quiet(name, errout0,
472 SOSCreateError(kSOSErrorNoCircleName, CFSTR("No ring name"), NULL, error));
473 require_action_quiet(SOSRingCheckType(type, error), errout0,
474 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Unknown ring type"), NULL, error));
475 require_action_quiet((r->unSignedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
476 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate unsigned information area"), NULL, error));
477 require_action_quiet((r->signedInformation = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
478 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signed information area"), NULL, error));
479 require_action_quiet((r->signatures = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
480 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate signature area"), NULL, error));
481 require_action_quiet((r->data = CFDictionaryCreateMutableForCFTypes(ALLOCATOR)), errout,
482 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate data area"), NULL, error));
483
484 require_action_quiet(SOSRingSetName(r, name), errout,
485 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring name area"), NULL, error));
486 require_action_quiet(SOSRingSetType(r, type), errout,
487 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring type"), NULL, error));
488 require_action_quiet(SOSRingSetVersion(r), errout,
489 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring version"), NULL, error));
490 require_action_quiet(SOSRingSetIdentifier(r), errout,
491 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate ring identifier"), NULL, error));
492
493 CFMutableSetRef peerIDs = CFSetCreateMutableForSOSPeerIDs();
494 require_action_quiet(SOSRingSetApplicants(r, peerIDs), errout,
495 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate applicant area"), NULL, error));
496 CFReleaseNull(peerIDs);
497
498 CFMutableSetRef rejectedIDs = CFSetCreateMutableForSOSPeerIDs();
499 require_action_quiet(SOSRingSetRejections(r, rejectedIDs), errout,
500 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate rejection area"), NULL, error));
501 CFReleaseNull(rejectedIDs);
502
503 require_action_quiet(SOSRingSetGeneration(r, gen), errout,
504 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate generation count"), NULL, error));
505
506 peerIDs = CFSetCreateMutableForSOSPeerIDs();
507 require_action_quiet(SOSRingSetPeerIDs(r, peerIDs), errout,
508 SOSCreateError(kSOSErrorAllocationFailure, CFSTR("Failed to allocate PeerID"), NULL, error));
509 CFReleaseNull(gen);
510 CFReleaseNull(peerIDs);
511
512 return r;
513 errout:
514 CFReleaseNull(r->unSignedInformation);
515 CFReleaseNull(r->signedInformation);
516 CFReleaseNull(r->signatures);
517 CFReleaseNull(r->data);
518 errout0:
519 CFReleaseNull(gen);
520 CFReleaseNull(r);
521 return NULL;
522 }
523
524
525 static void SOSRingDestroy(CFTypeRef aObj) {
526 SOSRingRef c = (SOSRingRef) aObj;
527
528 CFReleaseNull(c->unSignedInformation);
529 CFReleaseNull(c->signedInformation);
530 CFReleaseNull(c->data);
531 CFReleaseNull(c->signatures);
532 }
533
534
535 SOSRingRef SOSRingCopyRing(SOSRingRef original, CFErrorRef *error) {
536 SOSRingRef r = CFTypeAllocate(SOSRing, struct __OpaqueSOSRing, ALLOCATOR);
537
538 assert(original);
539 r->unSignedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->unSignedInformation);
540 r->signedInformation = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signedInformation);
541 r->signatures = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->signatures);
542 r->data = CFDictionaryCreateMutableCopy(ALLOCATOR, 0, original->data);
543
544 return r;
545 }
546
547 bool SOSRingIsEmpty_Internal(SOSRingRef ring) {
548 return CFSetGetCount(SOSRingGetPeerIDs(ring)) == 0;
549 }
550
551 bool SOSRingIsOffering_Internal(SOSRingRef ring) {
552 return SOSRingCountPeers(ring) == 1;
553 }
554
555 bool SOSRingResetToEmpty_Internal(SOSRingRef ring, CFErrorRef *error) {
556 SOSGenCountRef gen = NULL;
557 CFSetRemoveAllValues(SOSRingGetApplicants(ring));
558 CFSetRemoveAllValues(SOSRingGetRejections(ring));
559 CFSetRemoveAllValues(SOSRingGetPeerIDs(ring));
560 CFDictionaryRemoveAllValues(ring->signatures);
561 SOSRingSetGeneration(ring, gen = SOSGenerationCreate());
562 CFReleaseNull(gen);
563 return true;
564 }
565
566 // MARK: PeerIDs in Ring
567
568 int SOSRingCountPeers(SOSRingRef ring) {
569 SOSRingAssertStable(ring);
570 return (int) CFSetGetCount(SOSRingGetPeerIDs(ring));
571 }
572
573
574 bool SOSRingHasPeerWithID(SOSRingRef ring, CFStringRef peerid, CFErrorRef *error) {
575 SOSRingAssertStable(ring);
576 return CFSetContainsValue(SOSRingGetPeerIDs(ring), peerid);
577 }
578
579 // MARK: Ring Signatures
580
581
582 static inline CFDictionaryRef SOSRingGetSignatures(SOSRingRef ring) {
583 return ring->signatures;
584 }
585
586 static inline CFDataRef SOSRingGetSignatureForPeerID(SOSRingRef ring, CFStringRef peerID) {
587 if(!ring || !peerID) return NULL;
588 CFDataRef result = NULL;
589 CFTypeRef value = (CFDataRef)CFDictionaryGetValue(SOSRingGetSignatures(ring), peerID);
590 if (isData(value)) result = (CFDataRef) value;
591 return result;
592 }
593
594 static CFDataRef SOSRingCreateHash(const struct ccdigest_info *di, SOSRingRef ring, CFErrorRef *error) {
595 uint8_t hash_result[di->output_size];
596
597 size_t dersize = der_sizeof_plist(ring->signedInformation, error);
598 if(dersize == 0) {
599 return false;
600 }
601 uint8_t *der = malloc(dersize);
602 if (der == NULL) {
603 return false;
604 }
605 if (der_encode_plist(ring->signedInformation, error, der, der+dersize) == NULL) {
606 free(der);
607 return false;
608 }
609
610 ccdigest(di, dersize, der, hash_result);
611 free(der);
612 return CFDataCreate(NULL, hash_result, di->output_size);
613 }
614
615 static bool SOSRingSetSignature(SOSRingRef ring, SecKeyRef privKey, CFDataRef signature, CFErrorRef *error) {
616 bool result = false;
617 SecKeyRef pubkey = SecKeyCreatePublicFromPrivate(privKey);
618 CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error);
619 require_quiet(pubKeyID, fail);
620 CFDictionarySetValue(ring->signatures, pubKeyID, signature);
621 result = true;
622 fail:
623 CFReleaseSafe(pubkey);
624 CFReleaseSafe(pubKeyID);
625 return result;
626 }
627
628 bool SOSRingRemoveSignatures(SOSRingRef ring, CFErrorRef *error) {
629 CFDictionaryRemoveAllValues(ring->signatures);
630 return true;
631 }
632
633 static CFDataRef SOSCopySignedHash(SecKeyRef privKey, CFDataRef hash, CFErrorRef *error) {
634 size_t siglen = SecKeyGetSize(privKey, kSecKeySignatureSize)+16;
635 uint8_t sig[siglen];
636 OSStatus stat = SecKeyRawSign(privKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash), sig, &siglen);
637 if(stat) {
638 return NULL;
639 }
640 return CFDataCreate(NULL, sig, siglen);
641 }
642
643 static bool SOSRingSign(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
644 if (!ring || !privKey) {
645 SOSCreateError(kSOSErrorBadSignature, CFSTR("SOSRingSign Lacking ring or private key"),
646 (error != NULL) ? *error : NULL, error);
647 return false;
648 }
649 const struct ccdigest_info *di = ccsha256_di();
650 CFDataRef hash = SOSRingCreateHash(di, ring, error);
651 CFDataRef signature = SOSCopySignedHash(privKey, hash, error);
652 SOSRingSetSignature(ring, privKey, signature, error);
653 CFRelease(signature);
654 CFReleaseNull(hash);
655 return true;
656 }
657
658 bool SOSRingVerifySignatureExists(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
659 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
660 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
661 CFReleaseNull(pubKeyID);
662 return NULL != signature;
663 }
664
665 bool SOSRingVerify(SOSRingRef ring, SecKeyRef pubKey, CFErrorRef *error) {
666 CFStringRef pubKeyID = SOSCopyIDOfKey(pubKey, error);
667 CFDataRef signature = SOSRingGetSignatureForPeerID(ring, pubKeyID);
668 CFReleaseNull(pubKeyID);
669 if(!signature) return false;
670 CFDataRef hash = SOSRingCreateHash(ccsha256_di(), ring, error);
671 bool success = SecKeyRawVerify(pubKey, kSecPaddingNone, CFDataGetBytePtr(hash), CFDataGetLength(hash),
672 CFDataGetBytePtr(signature), CFDataGetLength(signature)) == errSecSuccess;
673 CFReleaseNull(hash);
674 return success;
675 }
676
677 bool SOSRingVerifyPeerSigned(SOSRingRef ring, SOSPeerInfoRef peer, CFErrorRef *error) {
678 bool result = false;
679 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(peer, error);
680 require_quiet(pubkey, fail);
681
682 result = SOSRingVerify(ring, pubkey, error);
683
684 fail:
685 CFReleaseSafe(pubkey);
686 return result;
687 }
688
689 static bool SOSRingEnsureRingConsistency(SOSRingRef ring, CFErrorRef *error) {
690 secnotice("Development", "SOSRingEnsureRingConsistency requires ring membership and generation count consistency check", NULL);
691 return true;
692 }
693
694 bool SOSRingGenerationSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
695 if(!privKey || !ring) return false;
696 bool retval = false;
697 SOSRingGenerationIncrement(ring);
698 require_quiet(SOSRingEnsureRingConsistency(ring, error), fail);
699 require_quiet(SOSRingRemoveSignatures(ring, error), fail);
700 require_quiet(SOSRingSign(ring, privKey, error), fail);
701 retval = true;
702 fail:
703 return retval;
704 }
705
706 // MARK: Concordance
707
708 bool SOSRingConcordanceSign_Internal(SOSRingRef ring, SecKeyRef privKey, CFErrorRef *error) {
709 if(!privKey || !ring) return false;
710 bool retval = false;
711 require_quiet(SOSRingSign(ring, privKey, error), fail);
712 retval = true;
713 fail:
714 return retval;
715 }
716
717
718
719 // MARK: Debugging
720
721 static inline void CFSetForEachPeerID(CFSetRef set, void (^operation)(CFStringRef peerID)) {
722 CFSetForEach(set, ^(const void *value) {
723 CFStringRef peerID = (CFStringRef) value;
724 operation(peerID);
725 });
726 }
727
728 static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) {
729 CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0);
730
731 __block bool addSeparator = false;
732
733 if(peers) {
734 CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
735 if (addSeparator) {
736 CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
737 }
738 CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8);
739 CFStringAppend(result, spid);
740 CFReleaseNull(spid);
741
742 addSeparator = true;
743 });
744 }
745
746 return result;
747 }
748
749 CFDictionaryRef SOSRingCopyPeerIDList(SOSRingRef ring) {
750 CFStringRef peerIDS = CreateCommaSeparatedPeerIDs(SOSRingGetPeerIDs(ring));
751 CFStringRef applicantIDs = CreateCommaSeparatedPeerIDs(SOSRingGetApplicants(ring));
752 CFStringRef rejectIDs = CreateCommaSeparatedPeerIDs(SOSRingGetRejections(ring));
753 CFDictionaryRef list = CFDictionaryCreateForCFTypes(ALLOCATOR,
754 CFSTR("MEMBER"), peerIDS,
755 CFSTR("APPLICANTS"), applicantIDs,
756 CFSTR("REJECTS"), rejectIDs,
757 NULL);
758
759 CFReleaseNull(peerIDS);
760 CFReleaseNull(applicantIDs);
761 CFReleaseNull(rejectIDs);
762 return list;
763 }
764
765 CFStringRef SOSRingCopySignerList(SOSRingRef ring) {
766 __block bool addSeparator = false;
767 CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0);
768 CFDictionaryForEach(ring->signatures, ^(const void *key, const void *value) {
769 CFStringRef peerID = (CFStringRef) key;
770 CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8);
771 if (addSeparator)
772 CFStringAppendCString(signers, ", ", kCFStringEncodingUTF8);
773 CFStringAppend(signers, spid);
774 CFReleaseNull(spid);
775 addSeparator = true;
776 });
777 return signers;
778 }
779
780 static CFStringRef SOSRingCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOpts) {
781 SOSRingRef ring = (SOSRingRef) aObj;
782
783 SOSRingAssertStable(ring);
784
785 CFDictionaryRef peers = SOSRingCopyPeerIDList(ring);
786 CFStringRef signers = SOSRingCopySignerList(ring);
787 CFStringRef gcString = SOSGenerationCountCopyDescription(SOSRingGetGeneration(ring));
788
789 CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
790
791 CFStringAppendFormat(description, formatOpts, CFSTR("<SOSRing: '%@'"), SOSRingGetName(ring));
792 SOSGenerationCountWithDescription(SOSRingGetGeneration(ring), ^(CFStringRef gcString) {
793 CFStringAppendFormat(description, formatOpts, CFSTR("Gen: %@, "), gcString);
794 });
795 CFStringRef modifierID = CFStringCreateTruncatedCopy(SOSRingGetLastModifier(ring), 8);
796 CFStringAppendFormat(description, formatOpts, CFSTR("Mod: %@, "), modifierID);
797 CFReleaseNull(modifierID);
798
799 CFStringAppendFormat(description, formatOpts, CFSTR("P: [%@], "), CFDictionaryGetValue(peers, CFSTR("MEMBER")));
800 CFStringAppendFormat(description, formatOpts, CFSTR("A: [%@], "), CFDictionaryGetValue(peers, CFSTR("APPLICANTS")));
801 CFStringAppendFormat(description, formatOpts, CFSTR("R: [%@], "), CFDictionaryGetValue(peers, CFSTR("REJECTS")));
802 CFStringAppendFormat(description, formatOpts, CFSTR("S: [%@]>"), signers);
803
804 CFReleaseNull(gcString);
805 CFReleaseNull(peers);
806 CFReleaseNull(signers);
807 CFReleaseNull(peers);
808
809 return description;
810 }
811
812 #define SIGLEN 128
813
814