]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSRingTypes.m
Security-59306.61.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSRingTypes.m
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 "keychain/SecureObjectSync/SOSAccountPriv.h"
34 #include "keychain/SecureObjectSync/SOSInternal.h"
35 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
36 #include <AssertMacros.h>
37
38 // These need to track the ring type enums in SOSRingTypes.h
39 static ringFuncs ringTypes[] = {
40 &basic, // kSOSRingBase
41 &backup, // kSOSRingBackup
42 NULL, // kSOSRingPeerKeyed
43 NULL, // kSOSRingEntropyKeyed
44 NULL, // kSOSRingPKKeyed
45 &recovery, // kSOSRingRecovery
46 };
47 static const size_t typecount = sizeof(ringTypes) / sizeof(ringFuncs);
48
49 static bool SOSRingValidType(SOSRingType type) {
50 if(type >= typecount || ringTypes[type] == NULL) return false;
51 return true;
52 }
53
54 // MARK: Exported Functions
55
56
57 SOSRingRef SOSRingCreate(CFStringRef name, CFStringRef myPeerID, SOSRingType type, CFErrorRef *error) {
58 if(!SOSRingValidType(type)){
59 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
60 return NULL;
61 }
62 if(!(ringTypes[type]->sosRingCreate)){
63 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
64 return NULL;
65 }
66 return ringTypes[type]->sosRingCreate(name, myPeerID, error);
67 }
68
69 bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) {
70 SOSRingAssertStable(ring);
71 SOSRingType type = SOSRingGetType(ring);
72 if(!SOSRingValidType(type)){
73 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
74 return false;
75 }
76 if(!ringTypes[type]->sosRingResetToEmpty){
77 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
78 return false;
79 }
80 return ringTypes[type]->sosRingResetToEmpty(ring, myPeerID, error);
81 }
82
83 bool SOSRingResetToOffering(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
84 SOSRingAssertStable(ring);
85 SOSRingType type = SOSRingGetType(ring);
86 if(!SOSRingValidType(type)){
87 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
88 return false;
89 }
90 if(!ringTypes[type]->sosRingResetToOffering){
91 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
92 return false;
93 }
94 return ringTypes[type]->sosRingResetToOffering(ring, user_privkey, requestor, error);
95 }
96
97 SOSRingStatus SOSRingDeviceIsInRing(SOSRingRef ring, CFStringRef peerID) {
98 SOSRingAssertStable(ring);
99 SOSRingType type = SOSRingGetType(ring);
100 if(!(SOSRingValidType(type))){
101 return kSOSRingError;
102 }
103 if(!(ringTypes[type]->sosRingDeviceIsInRing)){
104 return kSOSRingError;
105 }
106 return ringTypes[type]->sosRingDeviceIsInRing(ring, peerID);
107 }
108
109 bool SOSRingApply(SOSRingRef ring, SecKeyRef user_pubkey, SOSFullPeerInfoRef fpi, CFErrorRef *error) {
110 SOSRingAssertStable(ring);
111 SOSRingType type = SOSRingGetType(ring);
112 if(!(SOSRingValidType(type))){
113 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
114 return false;
115 }
116 if(!(ringTypes[type]->sosRingApply)){
117 return true;
118 }
119 if(!(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, error))){
120 SOSCreateError(kSOSErrorBadSignature, CFSTR("FullPeerInfo fails userkey signature check"), NULL, error);
121 return false;
122 }
123
124 return ringTypes[type]->sosRingApply(ring, user_pubkey, fpi, error);
125 }
126
127 bool SOSRingWithdraw(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
128 SOSRingAssertStable(ring);
129 SOSRingType type = SOSRingGetType(ring);
130 if(!SOSRingValidType(type)){
131 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
132 return false;
133 }
134 if(!ringTypes[type]->sosRingWithdraw)
135 return true;
136
137 return ringTypes[type]->sosRingWithdraw(ring, user_privkey, requestor, error);
138 }
139
140 bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
141 SOSRingAssertStable(ring);
142 SOSRingType type = SOSRingGetType(ring);
143 if(!(SOSRingValidType(type))){
144 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
145 return false;
146 }
147 if(!(ringTypes[type]->sosRingGenerationSign)){
148 return true;
149 }
150 return ringTypes[type]->sosRingGenerationSign(ring, user_privkey, requestor, error);
151 }
152
153 bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
154 SOSRingAssertStable(ring);
155 SOSRingType type = SOSRingGetType(ring);
156 if(!(SOSRingValidType(type))){
157 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
158 return false;
159 }
160 if(!(ringTypes[type]->sosRingConcordanceSign)){
161 return true;
162 }
163 return ringTypes[type]->sosRingConcordanceSign(ring, requestor, error);
164 }
165
166 SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers,
167 SOSRingRef knownRing, SOSRingRef proposedRing,
168 SecKeyRef knownPubkey, SecKeyRef userPubkey,
169 CFStringRef excludePeerID, CFErrorRef *error) {
170 SOSRingAssertStable(knownRing);
171 SOSRingAssertStable(proposedRing);
172 SOSRingType type1 = SOSRingGetType(knownRing);
173 SOSRingType type2 = SOSRingGetType(proposedRing);
174 if(!(SOSRingValidType(type1))){
175 return kSOSConcordanceError;
176 }
177 if(!(SOSRingValidType(type2))){
178 return kSOSConcordanceError;
179 }
180 if((type1 != type2)){
181 return kSOSConcordanceError;
182 }
183
184 secnotice("ring", "concordance trust (%s)", ringTypes[type1]->typeName);
185 secnotice("ring", " knownRing: %@", knownRing);
186 secnotice("ring", " proposedRing: %@", proposedRing);
187 CFStringRef knownKeyID = SOSCopyIDOfKeyWithLength(knownPubkey, 8, NULL);
188 CFStringRef userKeyID = SOSCopyIDOfKeyWithLength(userPubkey, 8, NULL);
189 CFStringRef mypeerSPID = CFStringCreateTruncatedCopy(excludePeerID, 8);
190
191 secnotice("ring", "knownkey: %@ userkey: %@ myPeerID: %@", knownKeyID, userKeyID, mypeerSPID);
192 CFReleaseNull(knownKeyID);
193 CFReleaseNull(userKeyID);
194 CFReleaseNull(mypeerSPID);
195
196 if(!(ringTypes[type1]->sosRingConcordanceTrust)){
197 return kSOSConcordanceError;
198 }
199 return ringTypes[type1]->sosRingConcordanceTrust(me, peers, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID, error);
200 }
201
202 bool SOSRingAccept(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
203 SOSRingAssertStable(ring);
204 SOSRingType type = SOSRingGetType(ring);
205 if(!(SOSRingValidType(type))){
206 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
207 return false;
208 }
209 if(!(ringTypes[type]->sosRingAccept)){
210 return true;
211 }
212 return ringTypes[type]->sosRingAccept(ring, user_privkey, requestor, error);
213 }
214
215 bool SOSRingReject(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
216 SOSRingAssertStable(ring);
217 SOSRingType type = SOSRingGetType(ring);
218 if(!(SOSRingValidType(type))){
219 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
220 return false;
221 }
222 if(!(ringTypes[type]->sosRingReject)){
223 return true;
224 }
225 return ringTypes[type]->sosRingReject(ring, user_privkey, requestor, error);
226 }
227
228 bool SOSRingSetPayload(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
229 SOSRingAssertStable(ring);
230 SOSRingType type = SOSRingGetType(ring);
231 if(!(SOSRingValidType(type))){
232 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
233 return false;
234 }
235 if(!(ringTypes[type]->sosRingSetPayload)){
236 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
237 return false;
238 }
239 return ringTypes[type]->sosRingSetPayload(ring, user_privkey, payload, requestor, error);
240 }
241
242 CFDataRef SOSRingGetPayload(SOSRingRef ring, CFErrorRef *error) {
243 SOSRingAssertStable(ring);
244 SOSRingType type = SOSRingGetType(ring);
245 if(!SOSRingValidType(type)){
246 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
247 return NULL;
248 }
249 if(!ringTypes[type]->sosRingGetPayload){
250 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
251 return NULL;
252 };
253 return ringTypes[type]->sosRingGetPayload(ring, error);
254 }
255
256 CFSetRef SOSRingGetBackupViewset(SOSRingRef ring, CFErrorRef *error) {
257 SOSRingAssertStable(ring);
258 SOSRingType type = SOSRingGetType(ring);
259 if(kSOSRingBackup != type){
260 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
261 return NULL;
262 }
263 return SOSRingGetBackupViewset_Internal(ring);
264 }
265
266 // This returns one string with the view for the ring - we never used multi-view rings
267 CFStringRef SOSRingGetBackupView(SOSRingRef ring, CFErrorRef *error) {
268 __block CFStringRef result = NULL;
269 CFSetRef allTheViews = SOSRingGetBackupViewset(ring, error);
270 if(allTheViews) {
271 if(CFSetGetCount(allTheViews) == 1) {
272 CFSetForEach(allTheViews, ^(const void *value) {
273 result = asString(value, error);
274 });
275 }
276 } else {
277 SOSCreateError(kSOSErrorParam, CFSTR("Wrong set count for one return"), NULL, error);
278 }
279 return result;
280 }
281
282 static bool isBackupRing(SOSRingRef ring, CFErrorRef *error) {
283 SOSRingType type = SOSRingGetType(ring);
284 if(kSOSRingBackup != type){
285 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
286 return false;
287 }
288 return true;
289 }
290
291 bool SOSRingSetBackupKeyBag(SOSRingRef ring, SOSFullPeerInfoRef fpi, CFSetRef viewSet, SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
292 SOSRingAssertStable(ring);
293 CFDataRef bskb_as_data = NULL;
294 bool result = false;
295 if(!isBackupRing(ring, error)){
296 CFReleaseNull(bskb_as_data);
297 return result;
298 }
299
300 bskb_as_data = SOSBSKBCopyEncoded(bskb, error);
301 result = bskb_as_data &&
302 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
303 SOSRingSetPayload(ring, NULL, bskb_as_data, fpi, error);
304 CFReleaseNull(bskb_as_data);
305 return result;
306 }
307
308 SOSBackupSliceKeyBagRef SOSRingCopyBackupSliceKeyBag(SOSRingRef ring, CFErrorRef *error) {
309 SOSRingAssertStable(ring);
310
311 CFDataRef bskb_as_data = NULL;
312 SOSBackupSliceKeyBagRef result = NULL;
313 if(!isBackupRing(ring, error)){
314 return result;
315 }
316
317 bskb_as_data = SOSRingGetPayload(ring, error);
318 if(!bskb_as_data){
319 return result;
320 }
321 result = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskb_as_data, error);
322 return result;
323 }
324
325 bool SOSRingPKTrusted(SOSRingRef ring, SecKeyRef pubkey, CFErrorRef *error) {
326 SOSRingAssertStable(ring);
327 SOSRingType type = SOSRingGetType(ring);
328 if(!(SOSRingValidType(type))){
329 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
330 return false;
331 };
332 return SOSRingVerify(ring, pubkey, error);
333 }
334
335 bool SOSRingPeerTrusted(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
336 bool retval = false;
337 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(requestor);
338 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(pi, error);
339 require_quiet(pubkey, exit);
340 retval = SOSRingPKTrusted(ring, pubkey, error);
341 exit:
342 CFReleaseNull(pubkey);
343 return retval;
344 }