]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSRingBackup.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSRingBackup.m
1 //
2 // SOSRingBasic.c
3 // sec
4 //
5 // Created by Richard Murphy on 3/3/15.
6 //
7 //
8
9 #include "SOSRingBackup.h"
10
11 #include <AssertMacros.h>
12
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>
19
20 #include <Security/SecKey.h>
21 #include <Security/SecKeyPriv.h>
22 #include <CoreFoundation/CoreFoundation.h>
23
24 #include <utilities/SecCFWrappers.h>
25
26 #include <stdlib.h>
27 #include <assert.h>
28
29 #include "SOSRingUtils.h"
30 #include "SOSRingTypes.h"
31 #include "SOSRingBasic.h"
32
33 // MARK: Backup Ring Ops
34
35 static SOSRingRef SOSRingCreate_Backup(CFStringRef name, CFStringRef myPeerID, CFErrorRef *error) {
36 return SOSRingCreate_ForType(name, kSOSRingBackup, myPeerID, error);
37 }
38
39
40 // Make sure all the peers in the ring have access to the ring views
41 static bool SOSBackupRingPeersInViews(CFSetRef peers, SOSRingRef ring) {
42 CFSetRef ringViews = SOSBackupRingGetViews(ring, NULL);
43 if(!ringViews) return false;
44 __block bool retval = true;
45 SOSRingForEachPeerID(ring, ^(CFStringRef peerID) {
46 SOSPeerInfoRef peerInfo = SOSPeerInfoSetFindByID(peers, peerID);
47 if(peerInfo) {
48 CFSetForEach(ringViews, ^(const void *value) {
49 if(!SOSPeerInfoIsViewPermitted(peerInfo, (CFStringRef) value)) retval = false;
50 });
51 } else {
52 retval = false;
53 }
54 });
55 return retval;
56 }
57
58 // Make sure that the ring includes me if I'm enabled for its view.
59 static SOSConcordanceStatus SOSBackupRingEvaluateMyInclusion(SOSRingRef ring, SOSFullPeerInfoRef me) {
60 bool shouldBeInRing = false;
61 bool amInThisRing = false;
62
63 if (me) {
64 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(me);
65 CFStringRef peerID = SOSPeerInfoGetPeerID(pi);
66 CFSetRef ringViews = SOSRingGetBackupViewset_Internal(ring);
67 CFSetRef piViews = SOSPeerInfoGetPermittedViews(pi);
68 shouldBeInRing = CFSetIsSubset(ringViews, piViews);
69 amInThisRing = SOSRingHasPeerWithID(ring, peerID, NULL);
70 }
71
72 if(shouldBeInRing && !amInThisRing) return kSOSConcordanceMissingMe;
73 if(!shouldBeInRing && amInThisRing) return kSOSConcordanceImNotWorthy;
74 return kSOSConcordanceTrusted;
75 }
76
77 static SOSConcordanceStatus SOSRingPeerKeyConcordanceTrust_Backup(SOSFullPeerInfoRef me, CFSetRef peers, SOSRingRef knownRing, SOSRingRef proposedRing,
78 __unused SecKeyRef knownPubkey, SecKeyRef userPubkey,
79 CFStringRef excludePeerID, CFErrorRef *error) {
80 if(userPubkey == NULL) {
81 SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Concordance with no public key - need to validate application"), NULL, error);
82 return kSOSConcordanceNoUserKey;
83 }
84
85 if(SOSRingIsOlderGeneration(proposedRing, knownRing)) {
86 SOSCreateError(kSOSErrorReplay, CFSTR("Bad generation"), NULL, error);
87 return kSOSConcordanceGenOld;
88 }
89
90
91 if (SOSRingIsEmpty_Internal(proposedRing)) {
92 return kSOSConcordanceTrusted;
93 }
94
95 SOSConcordanceStatus localstatus = SOSBackupRingEvaluateMyInclusion(proposedRing, me);
96 if(localstatus == kSOSConcordanceMissingMe) {
97 SOSCreateError(kSOSErrorReplay, CFSTR("Improper exclusion of this peer"), NULL, error);
98 return localstatus;
99 }
100
101 if(localstatus == kSOSConcordanceImNotWorthy) {
102 SOSCreateError(kSOSErrorReplay, CFSTR("Improper inclusion of this peer"), NULL, error);
103 return localstatus;
104 }
105
106 if(!SOSBackupRingPeersInViews(peers, proposedRing)) {
107 return kSOSConcordanceInvalidMembership;
108 }
109
110 return GetSignersStatus_Transitive(peers, knownRing, proposedRing, userPubkey, excludePeerID, error);
111 }
112
113 bool SOSBackupRingSetViews(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFSetRef viewSet, CFErrorRef *error) {
114 CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
115 SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
116 bool retval = priv && myPeerID &&
117 SOSRingSetLastModifier(ring, myPeerID) &&
118 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
119 SOSRingGenerationSign_Internal(ring, priv, error);
120 CFReleaseNull(priv);
121 return retval;
122 }
123
124 CFSetRef SOSBackupRingGetViews(SOSRingRef ring, CFErrorRef *error) {
125 return SOSRingGetBackupViewset_Internal(ring);
126 }
127
128 ringFuncStruct backup = {
129 "Backup",
130 1,
131 SOSRingCreate_Backup,
132 SOSRingResetToEmpty_Basic,
133 SOSRingResetToOffering_Basic,
134 SOSRingDeviceIsInRing_Basic,
135 SOSRingApply_Basic,
136 SOSRingWithdraw_Basic,
137 SOSRingGenerationSign_Basic,
138 SOSRingConcordanceSign_Basic,
139 SOSRingPeerKeyConcordanceTrust_Backup,
140 NULL,
141 NULL,
142 SOSRingSetPayload_Basic,
143 SOSRingGetPayload_Basic,
144 };