]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSRingTypes.c
845ea54b955609864bcfda9bca63f0dae819b109
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSRingTypes.c
1 /*
2 * Copyright (c) 2015-2016 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 // SOSRingTypes.c
26 //
27
28 #include "SOSRing.h"
29 #include "SOSRingTypes.h"
30 #include "SOSRingBasic.h"
31 #include "SOSRingBackup.h"
32 #include "SOSRingRecovery.h"
33 #include <Security/SecureObjectSync/SOSAccountPriv.h>
34 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
35
36 // These need to track the ring type enums in SOSRingTypes.h
37 static ringFuncs ringTypes[] = {
38 &basic, // kSOSRingBase
39 &backup, // kSOSRingBackup
40 NULL, // kSOSRingPeerKeyed
41 NULL, // kSOSRingEntropyKeyed
42 NULL, // kSOSRingPKKeyed
43 &recovery, // kSOSRingRecovery
44 };
45 static const size_t typecount = sizeof(ringTypes) / sizeof(ringFuncs);
46
47 static bool SOSRingValidType(SOSRingType type) {
48 if(type >= typecount || ringTypes[type] == NULL) return false;
49 return true;
50 }
51
52 // MARK: Exported Functions
53
54
55 SOSRingRef SOSRingCreate(CFStringRef name, CFStringRef myPeerID, SOSRingType type, CFErrorRef *error) {
56 require(SOSRingValidType(type), errOut);
57 require(ringTypes[type]->sosRingCreate, errOut);
58 return ringTypes[type]->sosRingCreate(name, myPeerID, error);
59 errOut:
60 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
61 return NULL;
62 }
63
64 bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) {
65 SOSRingAssertStable(ring);
66 SOSRingType type = SOSRingGetType(ring);
67 require(SOSRingValidType(type), errOut);
68 require(ringTypes[type]->sosRingResetToEmpty, errOut);
69 return ringTypes[type]->sosRingResetToEmpty(ring, myPeerID, error);
70 errOut:
71 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
72 return false;
73 }
74
75 bool SOSRingResetToOffering(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
76 SOSRingAssertStable(ring);
77 SOSRingType type = SOSRingGetType(ring);
78 require(SOSRingValidType(type), errOut);
79 require(ringTypes[type]->sosRingResetToOffering, errOut);
80 return ringTypes[type]->sosRingResetToOffering(ring, user_privkey, requestor, error);
81 errOut:
82 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
83 return false;
84 }
85
86 SOSRingStatus SOSRingDeviceIsInRing(SOSRingRef ring, CFStringRef peerID) {
87 SOSRingAssertStable(ring);
88 SOSRingType type = SOSRingGetType(ring);
89 require(SOSRingValidType(type), errOut);
90 require(ringTypes[type]->sosRingDeviceIsInRing, errOut);
91 return ringTypes[type]->sosRingDeviceIsInRing(ring, peerID);
92 errOut:
93 return kSOSRingError;
94 }
95
96 bool SOSRingApply(SOSRingRef ring, SecKeyRef user_pubkey, SOSFullPeerInfoRef fpi, CFErrorRef *error) {
97 SOSRingAssertStable(ring);
98 SOSRingType type = SOSRingGetType(ring);
99 require(SOSRingValidType(type), errOut);
100 require(ringTypes[type]->sosRingApply, shortCircuit);
101 require_quiet(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, error), errOut2);
102
103 return ringTypes[type]->sosRingApply(ring, user_pubkey, fpi, error);
104 errOut:
105 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
106 return false;
107 errOut2:
108 SOSCreateError(kSOSErrorBadSignature, CFSTR("FullPeerInfo fails userkey signature check"), NULL, error);
109 return false;
110 shortCircuit:
111 return true;
112 }
113
114 bool SOSRingWithdraw(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
115 SOSRingAssertStable(ring);
116 SOSRingType type = SOSRingGetType(ring);
117 require(SOSRingValidType(type), errOut);
118 require(ringTypes[type]->sosRingWithdraw, shortCircuit);
119 return ringTypes[type]->sosRingWithdraw(ring, user_privkey, requestor, error);
120 errOut:
121 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
122 return false;
123 shortCircuit:
124 return true;
125 }
126
127 bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
128 SOSRingAssertStable(ring);
129 SOSRingType type = SOSRingGetType(ring);
130 require(SOSRingValidType(type), errOut);
131 require(ringTypes[type]->sosRingGenerationSign, shortCircuit);
132 return ringTypes[type]->sosRingGenerationSign(ring, user_privkey, requestor, error);
133 errOut:
134 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
135 return false;
136 shortCircuit:
137 return true;
138 }
139
140 bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
141 SOSRingAssertStable(ring);
142 SOSRingType type = SOSRingGetType(ring);
143 require(SOSRingValidType(type), errOut);
144 require(ringTypes[type]->sosRingConcordanceSign, shortCircuit);
145 return ringTypes[type]->sosRingConcordanceSign(ring, requestor, error);
146 errOut:
147 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
148 return false;
149 shortCircuit:
150 return true;
151 }
152
153 SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers,
154 SOSRingRef knownRing, SOSRingRef proposedRing,
155 SecKeyRef knownPubkey, SecKeyRef userPubkey,
156 CFStringRef excludePeerID, CFErrorRef *error) {
157 SOSRingAssertStable(knownRing);
158 SOSRingAssertStable(proposedRing);
159 SOSRingType type1 = SOSRingGetType(knownRing);
160 SOSRingType type2 = SOSRingGetType(proposedRing);
161 require(SOSRingValidType(type1), errOut);
162 require(SOSRingValidType(type2), errOut);
163 require(type1 == type2, errOut);
164
165 secnotice("ring", "concordance trust (%s) knownRing: %@ proposedRing: %@ knownkey: %@ userkey: %@ excluded: %@",
166 ringTypes[type1]->typeName, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID);
167
168 require(ringTypes[type1]->sosRingConcordanceTrust, errOut);
169 return ringTypes[type1]->sosRingConcordanceTrust(me, peers, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID, error);
170 errOut:
171 return kSOSConcordanceError;
172 }
173
174 bool SOSRingAccept(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
175 SOSRingAssertStable(ring);
176 SOSRingType type = SOSRingGetType(ring);
177 require(SOSRingValidType(type), errOut);
178 require(ringTypes[type]->sosRingAccept, shortCircuit);
179 return ringTypes[type]->sosRingAccept(ring, user_privkey, requestor, error);
180 errOut:
181 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
182 return false;
183 shortCircuit:
184 return true;
185 }
186
187 bool SOSRingReject(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
188 SOSRingAssertStable(ring);
189 SOSRingType type = SOSRingGetType(ring);
190 require(SOSRingValidType(type), errOut);
191 require(ringTypes[type]->sosRingReject, shortCircuit);
192 return ringTypes[type]->sosRingReject(ring, user_privkey, requestor, error);
193 errOut:
194 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
195 return false;
196 shortCircuit:
197 return true;
198 }
199
200 bool SOSRingSetPayload(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
201 SOSRingAssertStable(ring);
202 SOSRingType type = SOSRingGetType(ring);
203 require(SOSRingValidType(type), errOut);
204 require(ringTypes[type]->sosRingSetPayload, errOut);
205 return ringTypes[type]->sosRingSetPayload(ring, user_privkey, payload, requestor, error);
206 errOut:
207 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
208 return false;
209 }
210
211 CFDataRef SOSRingGetPayload(SOSRingRef ring, CFErrorRef *error) {
212 SOSRingAssertStable(ring);
213 SOSRingType type = SOSRingGetType(ring);
214 require(SOSRingValidType(type), errOut);
215 require(ringTypes[type]->sosRingGetPayload, errOut);
216 return ringTypes[type]->sosRingGetPayload(ring, error);
217 errOut:
218 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
219 return NULL;
220 }
221
222 CFSetRef SOSRingGetBackupViewset(SOSRingRef ring, CFErrorRef *error) {
223 SOSRingAssertStable(ring);
224 SOSRingType type = SOSRingGetType(ring);
225 require(kSOSRingBackup == type, errOut);
226 return SOSRingGetBackupViewset_Internal(ring);
227 errOut:
228 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
229 return NULL;
230 }
231
232 static bool isBackupRing(SOSRingRef ring, CFErrorRef *error) {
233 SOSRingType type = SOSRingGetType(ring);
234 require_quiet(kSOSRingBackup == type, errOut);
235 return true;
236 errOut:
237 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
238 return false;
239 }
240
241 bool SOSRingSetBackupKeyBag(SOSRingRef ring, SOSFullPeerInfoRef fpi, CFSetRef viewSet, SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
242 SOSRingAssertStable(ring);
243 CFDataRef bskb_as_data = NULL;
244 bool result = false;
245 require_quiet(isBackupRing(ring, error), errOut);
246
247 bskb_as_data = SOSBSKBCopyEncoded(bskb, error);
248 result = bskb_as_data &&
249 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
250 SOSRingSetPayload(ring, NULL, bskb_as_data, fpi, error);
251 errOut:
252 CFReleaseNull(bskb_as_data);
253 return result;
254 }
255
256 SOSBackupSliceKeyBagRef SOSRingCopyBackupSliceKeyBag(SOSRingRef ring, CFErrorRef *error) {
257 SOSRingAssertStable(ring);
258
259 CFDataRef bskb_as_data = NULL;
260 SOSBackupSliceKeyBagRef result = NULL;
261 require_quiet(isBackupRing(ring, error), errOut);
262
263 bskb_as_data = SOSRingGetPayload(ring, error);
264 require_quiet(bskb_as_data, errOut);
265
266 result = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskb_as_data, error);
267
268 errOut:
269 return result;
270 }
271
272
273 bool SOSRingPKTrusted(SOSRingRef ring, SecKeyRef pubkey, CFErrorRef *error) {
274 SOSRingAssertStable(ring);
275 SOSRingType type = SOSRingGetType(ring);
276 require(SOSRingValidType(type), errOut);
277 return SOSRingVerify(ring, pubkey, error);
278 errOut:
279 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
280 return false;
281 }
282
283 bool SOSRingPeerTrusted(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
284 bool retval = false;
285 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(requestor);
286 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(pi, error);
287 require_quiet(pubkey, exit);
288 retval = SOSRingPKTrusted(ring, pubkey, error);
289 exit:
290 CFReleaseNull(pubkey);
291 return retval;
292 }