5 // Created by Richard Murphy on 3/3/15.
9 #include "SOSRingBackup.h"
11 #include <AssertMacros.h>
13 #include "keychain/SecureObjectSync/SOSInternal.h"
14 #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
15 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
16 #include "keychain/SecureObjectSync/SOSCircle.h"
17 #include <Security/SecureObjectSync/SOSViews.h>
18 #include <Security/SecFramework.h>
20 #include <Security/SecKey.h>
21 #include <Security/SecKeyPriv.h>
22 #include <CoreFoundation/CoreFoundation.h>
24 #include <utilities/SecCFWrappers.h>
28 #include "SOSRingUtils.h"
29 #include "SOSRingTypes.h"
30 #include "SOSRingBasic.h"
32 // MARK: Backup Ring Ops
34 static SOSRingRef SOSRingCreate_Backup(CFStringRef name, CFStringRef myPeerID, CFErrorRef *error) {
35 return SOSRingCreate_ForType(name, kSOSRingBackup, myPeerID, error);
39 // Make sure all the peers in the ring have access to the ring views
40 static bool SOSBackupRingPeersInViews(CFSetRef peers, SOSRingRef ring) {
41 CFSetRef ringViews = SOSBackupRingGetViews(ring, NULL);
42 if(!ringViews) return false;
43 __block bool retval = true;
44 SOSRingForEachPeerID(ring, ^(CFStringRef peerID) {
45 SOSPeerInfoRef peerInfo = SOSPeerInfoSetFindByID(peers, peerID);
47 CFSetForEach(ringViews, ^(const void *value) {
48 if(!SOSPeerInfoIsViewPermitted(peerInfo, (CFStringRef) value)) retval = false;
57 // Make sure that the ring includes me if I'm enabled for its view.
58 static SOSConcordanceStatus SOSBackupRingEvaluateMyInclusion(SOSRingRef ring, SOSFullPeerInfoRef me) {
59 bool shouldBeInRing = false;
60 bool amInThisRing = false;
63 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(me);
64 CFStringRef peerID = SOSPeerInfoGetPeerID(pi);
65 CFSetRef ringViews = SOSRingGetBackupViewset_Internal(ring);
66 CFSetRef piViews = SOSPeerInfoGetPermittedViews(pi);
67 shouldBeInRing = CFSetIsSubset(ringViews, piViews);
68 amInThisRing = SOSRingHasPeerWithID(ring, peerID, NULL);
71 if(shouldBeInRing && !amInThisRing) return kSOSConcordanceMissingMe;
72 if(!shouldBeInRing && amInThisRing) return kSOSConcordanceImNotWorthy;
73 return kSOSConcordanceTrusted;
76 static SOSConcordanceStatus SOSRingPeerKeyConcordanceTrust_Backup(SOSFullPeerInfoRef me, CFSetRef peers, SOSRingRef knownRing, SOSRingRef proposedRing,
77 __unused SecKeyRef knownPubkey, SecKeyRef userPubkey,
78 CFStringRef excludePeerID, CFErrorRef *error) {
79 if(userPubkey == NULL) {
80 SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Concordance with no public key - need to validate application"), NULL, error);
81 return kSOSConcordanceNoUserKey;
84 if(SOSRingIsOlderGeneration(proposedRing, knownRing)) {
85 SOSCreateError(kSOSErrorReplay, CFSTR("Bad generation"), NULL, error);
86 return kSOSConcordanceGenOld;
90 if (SOSRingIsEmpty_Internal(proposedRing)) {
91 return kSOSConcordanceTrusted;
94 SOSConcordanceStatus localstatus = SOSBackupRingEvaluateMyInclusion(proposedRing, me);
95 if(localstatus == kSOSConcordanceMissingMe) {
96 SOSCreateError(kSOSErrorReplay, CFSTR("Improper exclusion of this peer"), NULL, error);
100 if(localstatus == kSOSConcordanceImNotWorthy) {
101 SOSCreateError(kSOSErrorReplay, CFSTR("Improper inclusion of this peer"), NULL, error);
105 if(!SOSBackupRingPeersInViews(peers, proposedRing)) {
106 return kSOSConcordanceInvalidMembership;
109 return GetSignersStatus_Transitive(peers, knownRing, proposedRing, userPubkey, excludePeerID, error);
112 bool SOSBackupRingSetViews(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFSetRef viewSet, CFErrorRef *error) {
113 CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
114 SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
115 bool retval = priv && myPeerID &&
116 SOSRingSetLastModifier(ring, myPeerID) &&
117 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
118 SOSRingGenerationSign_Internal(ring, priv, error);
123 CFSetRef SOSBackupRingGetViews(SOSRingRef ring, CFErrorRef *error) {
124 return SOSRingGetBackupViewset_Internal(ring);
127 ringFuncStruct backup = {
130 SOSRingCreate_Backup,
131 SOSRingResetToEmpty_Basic,
132 SOSRingResetToOffering_Basic,
133 SOSRingDeviceIsInRing_Basic,
135 SOSRingWithdraw_Basic,
136 SOSRingGenerationSign_Basic,
137 SOSRingConcordanceSign_Basic,
138 SOSRingPeerKeyConcordanceTrust_Backup,
141 SOSRingSetPayload_Basic,
142 SOSRingGetPayload_Basic,