]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSAccountPersistence.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSAccountPersistence.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
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <AssertMacros.h>
28 #include "SOSViews.h"
29
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/SecNSAdditions.h>
32
33 #include <utilities/SecCoreCrypto.h>
34 #include <utilities/SecBuffer.h>
35
36 #include "keychain/SecureObjectSync/SOSKVSKeys.h"
37 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
38
39 #include "keychain/SecureObjectSync/SOSTransport.h"
40
41 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
42 #include <os/state_private.h>
43
44 #include "keychain/SecureObjectSync/SOSAccountPriv.h"
45 #import "keychain/SecureObjectSync/SOSAccountTrust.h"
46 #import "keychain/SecureObjectSync/SOSCircleDer.h"
47 #import "keychain/SecureObjectSync/SOSAccountTrustClassic.h"
48
49 @implementation SOSAccount (Persistence)
50
51
52 static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator,
53 SOSDataSourceFactoryRef factory,
54 CFErrorRef* error,
55 const uint8_t** der_p, const uint8_t *der_end)
56 {
57 SOSAccount* result = NULL;
58 SOSAccount* account = NULL;
59
60 CFArrayRef array = NULL;
61 CFDictionaryRef retiredPeers = NULL;
62
63 CFStringRef circle_name = factory->copy_name(factory);
64
65 {
66 CFDictionaryRef decoded_gestalt = NULL;
67 *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error,
68 *der_p, der_end);
69
70 if (*der_p == 0)
71 return NULL;
72
73 account = SOSAccountCreate(allocator, decoded_gestalt, factory);
74
75 CFReleaseNull(decoded_gestalt);
76 }
77 SOSAccountTrustClassic *trust = account.trust;
78
79 *der_p = der_decode_array(kCFAllocatorDefault, &array, error, *der_p, der_end);
80
81 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle;
82 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, der_end);
83 [trust setDepartureCode:(enum DepartureReason)tmp_departure_code];
84
85 bool userPublicTrusted;
86 *der_p = ccder_decode_bool(&userPublicTrusted, *der_p, der_end);
87 account.accountKeyIsTrusted = userPublicTrusted;
88
89 SecKeyRef userPublic = NULL;
90 SecKeyRef previousUserPublic = NULL;
91 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &userPublic, error, *der_p, der_end);
92 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &previousUserPublic, error, *der_p, der_end);
93 account.accountKey = userPublic;
94 account.previousAccountKey = previousUserPublic;
95 CFReleaseNull(userPublic);
96 CFReleaseNull(previousUserPublic);
97
98 {
99 CFDataRef parms = NULL;
100 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end);
101 [account setAccountKeyDerivationParameters:(__bridge_transfer NSData*) parms];
102 }
103
104 *der_p = der_decode_dictionary(kCFAllocatorDefault, (CFDictionaryRef *) &retiredPeers, error, *der_p, der_end);
105
106 if(*der_p != der_end) {
107 *der_p = NULL;
108 return result;
109 }
110
111 {
112 CFMutableSetRef retirees = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
113
114 CFDictionaryForEach(retiredPeers, ^(const void *key, const void *value) {
115 if (isData(value)) {
116 SOSPeerInfoRef retiree = SOSPeerInfoCreateFromData(kCFAllocatorDefault, NULL, (CFDataRef) value);
117
118 CFSetAddValue(retirees, retiree);
119
120 CFReleaseNull(retiree);
121 }
122 });
123
124 [trust setRetirees:(__bridge NSMutableSet *)retirees];
125 CFReleaseNull(retirees);
126 }
127
128 if(!array || !*der_p)
129 return result;
130
131 CFArrayForEach(array, ^(const void *value) {
132 CFDataRef circleData = NULL;
133 CFDataRef fullPeerInfoData = NULL;
134
135 if (isData(value)) {
136 circleData = (CFDataRef) value;
137 } else if (isArray(value)) {
138 CFArrayRef pair = (CFArrayRef) value;
139
140 CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0);
141 CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1);
142
143 if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) {
144 circleData = (CFDataRef) circleObject;
145 fullPeerInfoData = (CFDataRef) fullPeerInfoObject;
146 }
147 }
148
149 if (circleData) {
150 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error);
151 require_quiet(circle && CFEqualSafe(circle_name, SOSCircleGetName(circle)), fail);
152 [trust setTrustedCircle:circle];
153 CFReleaseNull(circle);
154
155 if(fullPeerInfoData) {
156 SOSFullPeerInfoRef identity = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, NULL);
157 trust.fullPeerInfo = identity;
158 CFReleaseNull(identity);
159 }
160
161 fail:
162 CFReleaseNull(circle);
163 }
164 });
165 CFReleaseNull(array);
166 require_action_quiet([account ensureFactoryCircles], fail,
167 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error));
168 result = account;
169
170 fail:
171
172 return result;
173 }
174
175 static const uint8_t* der_decode_data_optional(CFAllocatorRef allocator,
176 CFDataRef* data, CFErrorRef *error,
177 const uint8_t* der, const uint8_t *der_end)
178 {
179 const uint8_t *dt_end = der_decode_data(allocator, data, NULL, der, der_end);
180
181 return dt_end ? dt_end : der;
182 }
183
184 static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator,
185 SOSDataSourceFactoryRef factory,
186 CFErrorRef* error,
187 const uint8_t** der_p, const uint8_t *der_end)
188 {
189 SOSAccount* account = NULL;
190 SOSAccount* result = NULL;
191
192 {
193 CFDictionaryRef decoded_gestalt = NULL;
194 *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error,
195 *der_p, der_end);
196
197 if (*der_p == 0)
198 return NULL;
199
200 account = SOSAccountCreate(kCFAllocatorDefault, decoded_gestalt, factory);
201 CFReleaseNull(decoded_gestalt);
202 }
203
204 enum DepartureReason departure_code = 0;
205 SOSAccountTrustClassic *trust = account.trust;
206
207 {
208 SOSCircleRef circle = SOSCircleCreateFromDER(kCFAllocatorDefault, error, der_p, der_end);
209 [trust setTrustedCircle:circle];
210 CFReleaseNull(circle);
211 }
212
213 {
214 SOSFullPeerInfoRef identity = NULL;
215 *der_p = der_decode_fullpeer_or_null(kCFAllocatorDefault, &identity, error, *der_p, der_end);
216 trust.fullPeerInfo = identity;
217 CFReleaseNull(identity);
218 }
219
220 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle;
221 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, der_end);
222 bool userPublicTrusted;
223
224 *der_p = ccder_decode_bool(&userPublicTrusted, *der_p, der_end);
225 account.accountKeyIsTrusted = userPublicTrusted;
226
227 {
228 SecKeyRef userPublic = NULL;
229 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &userPublic, error, *der_p, der_end);
230 account.accountKey = userPublic;
231 CFReleaseNull(userPublic);
232 }
233
234 {
235 SecKeyRef previousUserPublic = NULL;
236 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &previousUserPublic, error, *der_p, der_end);
237 account.previousAccountKey = previousUserPublic;
238 CFReleaseNull(previousUserPublic);
239 }
240
241 {
242 CFDataRef parms = NULL;
243 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end);
244 account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms;
245 }
246
247 {
248 CFSetRef retirees = SOSPeerInfoSetCreateFromArrayDER(kCFAllocatorDefault, &kSOSPeerSetCallbacks, error, der_p, der_end);
249 [trust setRetirees:(__bridge NSMutableSet *)retirees];
250 }
251
252 {
253 CFDataRef bKey = NULL;
254 *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end);
255 if(bKey != NULL)
256 [account setBackup_key:(__bridge_transfer NSData *)bKey];
257 }
258
259 departure_code = (enum DepartureReason) tmp_departure_code;
260
261 [trust setDepartureCode:departure_code];
262 require_action_quiet(*der_p && *der_p == der_end, fail,
263 SOSCreateError(kSOSErrorBadFormat, CFSTR("Didn't consume all bytes v7"), (error != NULL) ? *error : NULL, error));
264
265 result = account;
266
267 fail:
268 return result;
269 }
270
271
272 static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator,
273 SOSDataSourceFactoryRef factory,
274 CFErrorRef* error,
275 const uint8_t** der_p, const uint8_t *der_end)
276 {
277 SOSAccount* account = NULL;
278 SOSAccount* result = NULL;
279
280 {
281 CFDictionaryRef decoded_gestalt = NULL;
282 *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error,
283 *der_p, der_end);
284
285 if (*der_p == 0) {
286 CFReleaseNull(decoded_gestalt);
287 return NULL;
288 }
289
290 account = SOSAccountCreate(kCFAllocatorDefault, decoded_gestalt, factory);
291 CFReleaseNull(decoded_gestalt);
292 }
293
294 SOSAccountTrustClassic *trust = account.trust;
295
296 {
297 SOSCircleRef circle = SOSCircleCreateFromDER(kCFAllocatorDefault, error, der_p, der_end);
298 [trust setTrustedCircle:circle];
299 CFReleaseNull(circle);
300 }
301
302 {
303 SOSFullPeerInfoRef identity = NULL;
304 *der_p = der_decode_fullpeer_or_null(kCFAllocatorDefault, &identity, error, *der_p, der_end);
305 trust.fullPeerInfo = identity;
306 CFReleaseNull(identity);
307 }
308
309 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle;
310 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, der_end);
311 [trust setDepartureCode:(enum DepartureReason) tmp_departure_code];
312
313 bool userPublicTrusted;
314 *der_p = ccder_decode_bool(&userPublicTrusted, *der_p, der_end);
315 account.accountKeyIsTrusted = userPublicTrusted;
316
317 {
318 SecKeyRef userPublic = NULL;
319 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &userPublic, error, *der_p, der_end);
320 account.accountKey = userPublic;
321 CFReleaseNull(userPublic);
322 }
323
324 {
325 SecKeyRef previousUserPublic = NULL;
326 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &previousUserPublic, error, *der_p, der_end);
327 account.previousAccountKey = previousUserPublic;
328 CFReleaseNull(previousUserPublic);
329 }
330
331 {
332 CFDataRef parms;
333 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end);
334 account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms;
335 parms = NULL;
336 }
337
338 {
339 CFMutableSetRef retirees = SOSPeerInfoSetCreateFromArrayDER(kCFAllocatorDefault, &kSOSPeerSetCallbacks, error, der_p, der_end);
340 [trust setRetirees:(__bridge NSMutableSet *)retirees];
341 CFReleaseNull(retirees);
342 }
343
344 CFDataRef bKey = NULL;
345 *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end);
346 {
347 CFDictionaryRef expansion = NULL;
348 *der_p = der_decode_dictionary(kCFAllocatorDefault, &expansion, error,
349 *der_p, der_end);
350
351 if (*der_p == 0) {
352 CFReleaseNull(bKey);
353 CFReleaseNull(expansion);
354 return NULL;
355 }
356
357 if(expansion) {
358 [trust setExpansion:(__bridge NSMutableDictionary *)(expansion)];
359 }
360 CFReleaseNull(expansion);
361 }
362 if(bKey) {
363 [account setBackup_key:[[NSData alloc] initWithData:(__bridge NSData * _Nonnull)(bKey)]];
364 }
365 CFReleaseNull(bKey);
366
367 require_action_quiet(*der_p && *der_p == der_end, fail,
368 SOSCreateError(kSOSErrorBadFormat, CFSTR("Didn't consume all bytes v7"), (error != NULL) ? *error : NULL, error));
369
370 result = account;
371
372 fail:
373 return result;
374 }
375
376 //
377 // Version History for Account
378 //
379 // 1-5 - InnsbruckTaos/Cab; Never supported even for upgrading.
380 // 6 - First version used in the field.
381 // 7 - One Circle version
382 // 8 - Adding expansion dictionary
383 //
384
385 #define CURRENT_ACCOUNT_PERSISTENT_VERSION 8
386
387 static SOSAccount* SOSAccountCreateFromDER(CFAllocatorRef allocator,
388 SOSDataSourceFactoryRef factory,
389 CFErrorRef* error,
390 const uint8_t** der_p, const uint8_t *der_end)
391 {
392 SOSAccount* account = NULL;
393 uint64_t version = 0;
394
395 SOSFullPeerInfoRef identity = NULL;
396
397 const uint8_t *sequence_end;
398 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
399 *der_p = ccder_decode_uint64(&version, *der_p, sequence_end);
400 if (*der_p == NULL) {
401 SOSCreateError(kSOSErrorBadFormat, CFSTR("Version parsing failed"), (error != NULL) ? *error : NULL, error);
402 return nil;
403 }
404
405 switch (version) {
406 case CURRENT_ACCOUNT_PERSISTENT_VERSION:
407 account = SOSAccountCreateFromRemainingDER_v8(allocator, factory, error, der_p, sequence_end);
408 break;
409
410 case 7:
411 account = SOSAccountCreateFromRemainingDER_v7(allocator, factory, error, der_p, sequence_end);
412 break;
413
414 case 6:
415 account = SOSAccountCreateFromRemainingDER_v6(allocator, factory, error, der_p, sequence_end);
416 break;
417
418 default:
419 SOSCreateErrorWithFormat(kSOSErrorBadFormat, (error != NULL) ? *error : NULL, error,
420 NULL, CFSTR("Unsupported version (%llu)"), version);
421 break;
422 }
423
424 if (!account) {
425 // Error should have been filled in above.
426 return nil;
427 }
428
429 if (*der_p != sequence_end) {
430 SOSCreateError(kSOSErrorBadFormat, CFSTR("Extra data at the end of saved acount"), (error != NULL) ? *error : NULL, error);
431 return nil;
432 }
433
434 identity = account.fullPeerInfo;
435 /* I may not always have an identity, but when I do, it has a private key */
436 if(identity) {
437 if(!(SOSFullPeerInfoPrivKeyExists(identity)))
438 {
439 SOSUnregisterTransportKeyParameter(account.key_transport);
440 SOSUnregisterTransportCircle((SOSCircleStorageTransport*)account.circle_transport);
441 SOSUnregisterTransportMessage(account.kvs_message_transport);
442 secnotice("account", "No private key associated with my_identity, resetting");
443 return nil;
444 } else {
445 SecKeyRef ppk = SOSFullPeerInfoCopyPubKey(identity, NULL);
446 account.peerPublicKey = ppk;
447 CFReleaseNull(ppk);
448 }
449 }
450
451 if (![account ensureFactoryCircles]) {
452 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error);
453 return nil;
454 }
455
456 SOSPeerInfoRef oldPI = CFRetainSafe(account.peerInfo);
457 if (oldPI && [account isInCircle: nil] == kSOSCCInCircle) {
458 SOSAccountCheckForAlwaysOnViews(account);
459 }
460 CFReleaseNull(oldPI);
461
462
463 [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) {
464 SOSAccountEnsureRecoveryRing(account);
465
466 secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreateFromDER");
467 account.key_interests_need_updating = true;
468 }];
469
470 SOSAccountEnsureUUID(account);
471
472 return account;
473 }
474
475 +(instancetype) accountFromDER: (const uint8_t**) der
476 end: (const uint8_t*) der_end
477 factory: (SOSDataSourceFactoryRef) factory
478 error: (NSError**) error {
479 CFErrorRef failure = NULL;
480 SOSAccount* result = SOSAccountCreateFromDER(kCFAllocatorDefault, factory, &failure, der, der_end);
481
482 if (result == nil) {
483 if (error) {
484 *error = (__bridge_transfer NSError*) failure;
485 failure = NULL;
486 }
487 }
488 CFReleaseNull(failure);
489
490 return result;
491 }
492
493 +(instancetype) accountFromData: (NSData*) data
494 factory: (SOSDataSourceFactoryRef) factory
495 error: (NSError**) error {
496 size_t size = [data length];
497 const uint8_t *der = [data bytes];
498 return [self accountFromDER: &der end: der+size factory: factory error: error];
499 }
500
501 CFMutableSetRef SOSPeerInfoSetCreateFromArrayDER(CFAllocatorRef allocator, const CFSetCallBacks *callbacks, CFErrorRef* error,
502 const uint8_t** der_p, const uint8_t *der_end);
503 size_t SOSPeerInfoSetGetDEREncodedArraySize(CFSetRef pia, CFErrorRef *error);
504 uint8_t* SOSPeerInfoSetEncodeToArrayDER(CFSetRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end);
505
506 /************************/
507
508
509 - (NSData*) encodedData: (NSError* __autoreleasing *) error {
510 NSUInteger expected = [self.trust getDEREncodedSize: self err:error];
511 if (expected == 0) return nil;
512
513 return [NSMutableData dataWithSpace:expected
514 DEREncode:^uint8_t *(size_t size, uint8_t *buffer) {
515 return [self.trust encodeToDER:self
516 err:error
517 start:buffer
518 end:buffer + size];
519 }];
520 }
521
522 @end