]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSRingTypes.m
Security-59306.101.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 SOSRingGenerationSign(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]->sosRingGenerationSign)){
91 return true;
92 }
93 return ringTypes[type]->sosRingGenerationSign(ring, user_privkey, requestor, error);
94 }
95
96 bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
97 SOSRingAssertStable(ring);
98 SOSRingType type = SOSRingGetType(ring);
99 if(!(SOSRingValidType(type))){
100 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
101 return false;
102 }
103 if(!(ringTypes[type]->sosRingConcordanceSign)){
104 return true;
105 }
106 return ringTypes[type]->sosRingConcordanceSign(ring, requestor, error);
107 }
108
109 SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers,
110 SOSRingRef knownRing, SOSRingRef proposedRing,
111 SecKeyRef knownPubkey, SecKeyRef userPubkey,
112 CFStringRef excludePeerID, CFErrorRef *error) {
113 SOSRingAssertStable(knownRing);
114 SOSRingAssertStable(proposedRing);
115 SOSRingType type1 = SOSRingGetType(knownRing);
116 SOSRingType type2 = SOSRingGetType(proposedRing);
117 if(!(SOSRingValidType(type1))){
118 return kSOSConcordanceError;
119 }
120 if(!(SOSRingValidType(type2))){
121 return kSOSConcordanceError;
122 }
123 if((type1 != type2)){
124 return kSOSConcordanceError;
125 }
126
127 secnotice("ring", "concordance trust (%s)", ringTypes[type1]->typeName);
128 secnotice("ring", " knownRing: %@", knownRing);
129 secnotice("ring", " proposedRing: %@", proposedRing);
130 CFStringRef knownKeyID = SOSCopyIDOfKeyWithLength(knownPubkey, 8, NULL);
131 CFStringRef userKeyID = SOSCopyIDOfKeyWithLength(userPubkey, 8, NULL);
132 CFStringRef mypeerSPID = CFStringCreateTruncatedCopy(excludePeerID, 8);
133
134 secnotice("ring", "knownkey: %@ userkey: %@ myPeerID: %@", knownKeyID, userKeyID, mypeerSPID);
135 CFReleaseNull(knownKeyID);
136 CFReleaseNull(userKeyID);
137 CFReleaseNull(mypeerSPID);
138
139 if(!(ringTypes[type1]->sosRingConcordanceTrust)){
140 return kSOSConcordanceError;
141 }
142 return ringTypes[type1]->sosRingConcordanceTrust(me, peers, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID, error);
143 }
144
145 bool SOSRingAccept(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
146 SOSRingAssertStable(ring);
147 SOSRingType type = SOSRingGetType(ring);
148 if(!(SOSRingValidType(type))){
149 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
150 return false;
151 }
152 if(!(ringTypes[type]->sosRingAccept)){
153 return true;
154 }
155 return ringTypes[type]->sosRingAccept(ring, user_privkey, requestor, error);
156 }
157
158 bool SOSRingReject(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
159 SOSRingAssertStable(ring);
160 SOSRingType type = SOSRingGetType(ring);
161 if(!(SOSRingValidType(type))){
162 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
163 return false;
164 }
165 if(!(ringTypes[type]->sosRingReject)){
166 return true;
167 }
168 return ringTypes[type]->sosRingReject(ring, user_privkey, requestor, error);
169 }
170
171 bool SOSRingSetPayload(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
172 SOSRingAssertStable(ring);
173 SOSRingType type = SOSRingGetType(ring);
174 if(!(SOSRingValidType(type))){
175 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
176 return false;
177 }
178 if(!(ringTypes[type]->sosRingSetPayload)){
179 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
180 return false;
181 }
182 return ringTypes[type]->sosRingSetPayload(ring, user_privkey, payload, requestor, error);
183 }
184
185 CFDataRef SOSRingGetPayload(SOSRingRef ring, CFErrorRef *error) {
186 SOSRingAssertStable(ring);
187 SOSRingType type = SOSRingGetType(ring);
188 if(!SOSRingValidType(type)){
189 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
190 return NULL;
191 }
192 if(!ringTypes[type]->sosRingGetPayload){
193 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
194 return NULL;
195 };
196 return ringTypes[type]->sosRingGetPayload(ring, error);
197 }
198
199 CFSetRef SOSRingGetBackupViewset(SOSRingRef ring, CFErrorRef *error) {
200 SOSRingAssertStable(ring);
201 SOSRingType type = SOSRingGetType(ring);
202 if(kSOSRingBackup != type){
203 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
204 return NULL;
205 }
206 return SOSRingGetBackupViewset_Internal(ring);
207 }
208
209 // This returns one string with the view for the ring - we never used multi-view rings
210 CFStringRef SOSRingGetBackupView(SOSRingRef ring, CFErrorRef *error) {
211 __block CFStringRef result = NULL;
212 CFSetRef allTheViews = SOSRingGetBackupViewset(ring, error);
213 if(allTheViews) {
214 if(CFSetGetCount(allTheViews) == 1) {
215 CFSetForEach(allTheViews, ^(const void *value) {
216 result = asString(value, error);
217 });
218 }
219 } else {
220 SOSCreateError(kSOSErrorParam, CFSTR("Wrong set count for one return"), NULL, error);
221 }
222 return result;
223 }
224
225 static bool isBackupRing(SOSRingRef ring, CFErrorRef *error) {
226 SOSRingType type = SOSRingGetType(ring);
227 if(kSOSRingBackup != type){
228 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
229 return false;
230 }
231 return true;
232 }
233
234 bool SOSRingSetBackupKeyBag(SOSRingRef ring, SOSFullPeerInfoRef fpi, CFSetRef viewSet, SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
235 SOSRingAssertStable(ring);
236 CFDataRef bskb_as_data = NULL;
237 bool result = false;
238 if(!isBackupRing(ring, error)){
239 CFReleaseNull(bskb_as_data);
240 return result;
241 }
242
243 bskb_as_data = SOSBSKBCopyEncoded(bskb, error);
244 result = bskb_as_data &&
245 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
246 SOSRingSetPayload(ring, NULL, bskb_as_data, fpi, error);
247 CFReleaseNull(bskb_as_data);
248 return result;
249 }
250
251 SOSBackupSliceKeyBagRef SOSRingCopyBackupSliceKeyBag(SOSRingRef ring, CFErrorRef *error) {
252 SOSRingAssertStable(ring);
253
254 CFDataRef bskb_as_data = NULL;
255 SOSBackupSliceKeyBagRef result = NULL;
256 if(!isBackupRing(ring, error)){
257 return result;
258 }
259
260 bskb_as_data = SOSRingGetPayload(ring, error);
261 if(!bskb_as_data){
262 return result;
263 }
264 result = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskb_as_data, error);
265 return result;
266 }
267
268 bool SOSRingPKTrusted(SOSRingRef ring, SecKeyRef pubkey, CFErrorRef *error) {
269 SOSRingAssertStable(ring);
270 SOSRingType type = SOSRingGetType(ring);
271 if(!(SOSRingValidType(type))){
272 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
273 return false;
274 };
275 return SOSRingVerify(ring, pubkey, error);
276 }
277
278 bool SOSRingPeerTrusted(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
279 bool retval = false;
280 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(requestor);
281 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(pi, error);
282 require_quiet(pubkey, exit);
283 retval = SOSRingPKTrusted(ring, pubkey, error);
284 exit:
285 CFReleaseNull(pubkey);
286 return retval;
287 }