]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSKVSKeys.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSKVSKeys.m
1 /*
2 * Copyright (c) 2013-2014 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 #include "keychain/SecureObjectSync/SOSKVSKeys.h"
25 #include <utilities/SecCFWrappers.h>
26 #include "keychain/SecureObjectSync/SOSAccountPriv.h"
27 #include <CoreFoundation/CFDate.h>
28
29 void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name) {
30 CFStringRef circle_key = SOSCircleKeyCreateWithName(name, NULL);
31 CFArrayAppendValue(array, circle_key);
32 CFReleaseNull(circle_key);
33 }
34
35 //
36 //
37 // MARK: KVS Keys
38 // TODO: Handle '|' and "¬" in other strings.
39 //
40 const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters");
41 const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync");
42 const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged");
43 const CFStringRef kSOSKVSRequiredKey = CFSTR("^Required");
44 const CFStringRef kSOSKVSOfficialDSIDKey = CFSTR("^OfficialDSID");
45 const CFStringRef kSOSKVSLastCleanupTimestampKey = CFSTR("tLastKVSKeyCleanup");
46 const CFStringRef kSOSKVSOTRConfigVersion = CFSTR("OTRConfigVersion");
47 const CFStringRef kSOSKVSWroteLastKeyParams = CFSTR("WroteLastKeyParams");
48 const CFStringRef kSOSKVSDebugScope = CFSTR("^DebugScope");
49
50 const CFStringRef sRingPrefix = CFSTR("~");
51 const CFStringRef sDebugInfoPrefix = CFSTR("dbg-");
52
53 const CFStringRef sWarningPrefix = CFSTR("!");
54 const CFStringRef sCirclePrefix = CFSTR("o");
55 const CFStringRef sRetirementPrefix = CFSTR("-");
56 const CFStringRef sLastKeyParametersPushedPrefix = CFSTR("k");
57 const CFStringRef sCircleSeparator = CFSTR("|");
58 const CFStringRef sFromToSeparator = CFSTR(":");
59
60 static CFStringRef copyStringEndingIn(CFMutableStringRef in, CFStringRef token) {
61 if(token == NULL) return CFStringCreateCopy(NULL, in);
62 CFRange tokenAt = CFStringFind(in, token, 0);
63 if(tokenAt.location == kCFNotFound) return NULL;
64 CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location));
65 CFStringDelete(in, CFRangeMake(0, tokenAt.location+1));
66 return retval;
67 }
68
69 SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) {
70 SOSKVSKeyType retval = kUnknownKey;
71
72 if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey;
73 else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey;
74 else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey;
75 else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey;
76 else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey;
77 else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey;
78 else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey;
79 else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey;
80 else retval = kMessageKey;
81
82 return retval;
83 }
84
85 bool SOSKVSKeyParse(SOSKVSKeyType keyType, CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to) {
86 bool retval = true;
87
88 switch(keyType) {
89 case kCircleKey:
90 if (circle) {
91 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
92 *circle = CFStringCreateWithSubstring(NULL, key, fromRange);
93 }
94 break;
95 case kMessageKey: {
96 CFStringRef mCircle = NULL;
97 CFStringRef mFrom = NULL;
98 CFStringRef mTo = NULL;
99 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
100
101 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
102 ((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) &&
103 (CFStringGetLength(mFrom) > 0) ) {
104 mTo = copyStringEndingIn(keycopy, NULL);
105 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
106 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
107 if (to && mTo) *to = CFStringCreateCopy(NULL, mTo);
108 } else {
109 retval = false;
110 }
111 CFReleaseNull(mCircle);
112 CFReleaseNull(mFrom);
113 CFReleaseNull(mTo);
114 CFReleaseNull(keycopy);
115 }
116 break;
117 case kRetirementKey: {
118 CFStringRef mCircle = NULL;
119 CFStringRef mPeer = NULL;
120 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
121 CFStringDelete(keycopy, CFRangeMake(0, 1));
122 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
123 ((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) {
124 if (circle) *circle = CFStringCreateCopy(NULL, mCircle);
125 if (from) *from = CFStringCreateCopy(NULL, mPeer);
126 } else {
127 retval = false;
128 }
129 CFReleaseNull(mCircle);
130 CFReleaseNull(mPeer);
131 CFReleaseNull(keycopy);
132 }
133 break;
134 case kRingKey:
135 if (ring) {
136 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
137 *ring = CFStringCreateWithSubstring(NULL, key, fromRange);
138 }
139 break;
140 case kDebugInfoKey:
141 /* piggybacking on peerinfo */
142 if (peerInfo) {
143 CFRange dbgRange = CFRangeMake(CFStringGetLength(sDebugInfoPrefix),
144 CFStringGetLength(key)-CFStringGetLength(sDebugInfoPrefix));
145 *peerInfo = CFStringCreateWithSubstring(NULL, key, dbgRange);
146 }
147 break;
148 case kAccountChangedKey:
149 case kParametersKey:
150 case kInitialSyncKey:
151 case kUnknownKey:
152 break;
153 case kLastKeyParameterKey:
154 if(from) {
155 CFStringRef mPrefix = NULL;
156 CFStringRef mFrom = NULL;
157 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
158
159 if( ((mPrefix = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
160 ((mFrom = copyStringEndingIn(keycopy, NULL)) != NULL)) {
161 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
162 } else {
163 retval = false;
164 }
165 CFReleaseNull(mPrefix);
166 CFReleaseNull(mFrom);
167 CFReleaseNull(keycopy);
168 }
169 break;
170 case kLastCircleKey:
171 if (circle && from) {
172 CFStringRef mCircle = NULL;
173 CFStringRef mFrom = NULL;
174 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
175
176 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
177 ((mFrom = copyStringEndingIn(keycopy, NULL)) != NULL)) {
178 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
179 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
180 } else {
181 retval = false;
182 }
183 CFReleaseNull(mCircle);
184 CFReleaseNull(mFrom);
185 CFReleaseNull(keycopy);
186 }
187
188 break;
189 }
190 return retval;
191 }
192
193 SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to)
194 {
195 SOSKVSKeyType retval = SOSKVSKeyGetKeyType(key);
196 bool parsed = SOSKVSKeyParse(retval, key, circle, peerInfo, ring, backupName, from, to);
197 if(!parsed) retval = kUnknownKey;
198
199 return retval;
200 }
201
202
203 CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error)
204 {
205 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error);
206 }
207
208
209 CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error)
210 {
211 if(!circleName) return NULL;
212 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName);
213 }
214
215 CFStringRef SOSRingKeyCreateWithName(CFStringRef ring_name, CFErrorRef *error)
216 {
217 if(!ring_name) return NULL;
218 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sRingPrefix, ring_name);
219 }
220
221 CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
222 {
223 CFStringRef circleName = NULL;
224
225 if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) {
226 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
227
228 CFReleaseNull(circleName);
229 }
230
231 return circleName;
232 }
233
234 CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
235 {
236 CFStringRef circleName = NULL;
237
238 if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) {
239 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
240
241 CFReleaseNull(circleName);
242 }
243 return circleName;
244 }
245
246 CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error)
247 {
248 CFStringRef fromPeer = NULL;
249
250 if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) {
251 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey);
252
253 CFReleaseNull(fromPeer);
254 }
255 return fromPeer;
256 }
257
258 CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name)
259 {
260 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
261 circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name);
262 }
263
264 CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name)
265 {
266 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name);
267 }
268
269 CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer)
270 {
271 return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer));
272 }
273
274 CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSMessage* transport, CFStringRef myName, CFStringRef peer_name){
275 CFErrorRef error = NULL;
276
277 CFStringRef circleName = [transport SOSTransportMessageGetCircleName];
278 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, myName);
279 CFReleaseSafe(error);
280 return result;
281 }
282
283 CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSMessage* transport, CFStringRef myID, CFStringRef peer_name) {
284 CFErrorRef error = NULL;
285
286 CFStringRef circleName = [transport SOSTransportMessageGetCircleName];
287
288 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, myID, peer_name);
289 CFReleaseSafe(error);
290 return result;
291 }
292
293 CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name)
294 {
295 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
296 sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name);
297 }
298
299 CFStringRef SOSRingKeyCreateWithRingName(CFStringRef ring_name)
300 {
301 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
302 sRingPrefix, ring_name);
303 }
304
305 CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name)
306 {
307 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name);
308 }
309
310 static CFStringRef SOSAccountCreateCompactDescription(SOSAccount* a) {
311
312 CFStringRef gestaltDescription = CFDictionaryCopySuperCompactDescription((__bridge CFDictionaryRef)(a.gestalt));
313
314 CFStringRef result = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), gestaltDescription);
315
316 CFReleaseNull(gestaltDescription);
317
318 return result;
319 }
320
321 //should be >KeyParameters|ourPeerID
322 CFStringRef SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID){
323
324 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
325 sLastKeyParametersPushedPrefix,kSOSKVSKeyParametersKey, sCircleSeparator, peerID);
326 }
327
328
329 //should be >KeyParameters|ourPeerID
330 CFStringRef SOSLastKeyParametersPushedKeyCreateWithAccountGestalt(SOSAccount* account){
331
332 CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
333 CFStringRef key= CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
334 sLastKeyParametersPushedPrefix, kSOSKVSKeyParametersKey, sCircleSeparator, gestaltInfo);
335 CFReleaseNull(gestaltInfo);
336 return key;
337 }
338
339 CFStringRef SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name)
340 {
341 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
342 sDebugInfoPrefix, type_name);
343 }
344