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