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