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 "SOSAccountPriv.h" 30 31#include <utilities/SecCFWrappers.h> 32#include <SecureObjectSync/SOSKVSKeys.h> 33 34SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, 35 SOSDataSourceFactoryRef factory, 36 CFErrorRef* error, 37 const uint8_t** der_p, const uint8_t *der_end) 38{ 39 SOSAccountRef account = NULL; 40 41 const uint8_t *sequence_end; 42 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); 43 44 { 45 CFDictionaryRef decoded_gestalt = NULL; 46 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, 47 *der_p, der_end); 48 49 if (*der_p == 0) 50 return NULL; 51 52 account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); 53 CFReleaseNull(decoded_gestalt); 54 } 55 56 CFArrayRef array = NULL; 57 *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); 58 59 *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); 60 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); 61 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); 62 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); 63 if (*der_p != sequence_end) 64 *der_p = NULL; 65 66 __block bool success = true; 67 68 require_quiet(array && *der_p, fail); 69 70 CFArrayForEach(array, ^(const void *value) { 71 if (success) { 72 if (isString(value)) { 73 CFDictionaryAddValue(account->circles, value, kCFNull); 74 } else { 75 CFDataRef circleData = NULL; 76 CFDataRef fullPeerInfoData = NULL; 77 78 if (isData(value)) { 79 circleData = (CFDataRef) value; 80 } else if (isArray(value)) { 81 CFArrayRef pair = (CFArrayRef) value; 82 83 CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); 84 CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); 85 86 if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { 87 circleData = (CFDataRef) circleObject; 88 fullPeerInfoData = (CFDataRef) fullPeerInfoObject; 89 } 90 } 91 92 if (circleData) { 93 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); 94 require_action_quiet(circle, fail, success = false); 95 96 CFStringRef circleName = SOSCircleGetName(circle); 97 CFDictionaryAddValue(account->circles, circleName, circle); 98 99 if (fullPeerInfoData) { 100 SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); 101 require_action_quiet(full_peer, fail, success = false); 102 103 CFDictionaryAddValue(account->circle_identities, circleName, full_peer); 104 CFReleaseNull(full_peer); 105 } 106 fail: 107 CFReleaseNull(circle); 108 } 109 } 110 } 111 }); 112 CFReleaseNull(array); 113 114 require_quiet(success, fail); 115 require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, 116 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); 117 118 return account; 119 120fail: 121 // Create a default error if we don't have one: 122 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Account DER"), NULL, error); 123 CFReleaseNull(account); 124 return NULL; 125} 126 127SOSAccountRef SOSAccountCreateFromDER_V2(CFAllocatorRef allocator, 128 SOSDataSourceFactoryRef factory, 129 CFErrorRef* error, 130 const uint8_t** der_p, const uint8_t *der_end) 131{ 132 SOSAccountRef account = NULL; 133 const uint8_t *dersave = *der_p; 134 const uint8_t *derend = der_end; 135 136 const uint8_t *sequence_end; 137 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); 138 139 { 140 CFDictionaryRef decoded_gestalt = NULL; 141 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, 142 *der_p, der_end); 143 144 if (*der_p == 0) 145 return NULL; 146 147 account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); 148 CFReleaseNull(decoded_gestalt); 149 } 150 151 CFArrayRef array = NULL; 152 *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); 153 154 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; 155 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); 156 *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); 157 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); 158 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); 159 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); 160 if (*der_p != sequence_end) 161 *der_p = NULL; 162 account->departure_code = (enum DepartureReason) tmp_departure_code; 163 164 __block bool success = true; 165 166 require_quiet(array && *der_p, fail); 167 168 CFArrayForEach(array, ^(const void *value) { 169 if (success) { 170 if (isString(value)) { 171 CFDictionaryAddValue(account->circles, value, kCFNull); 172 } else { 173 CFDataRef circleData = NULL; 174 CFDataRef fullPeerInfoData = NULL; 175 176 if (isData(value)) { 177 circleData = (CFDataRef) value; 178 } else if (isArray(value)) { 179 CFArrayRef pair = (CFArrayRef) value; 180 181 CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); 182 CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); 183 184 if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { 185 circleData = (CFDataRef) circleObject; 186 fullPeerInfoData = (CFDataRef) fullPeerInfoObject; 187 } 188 } 189 190 if (circleData) { 191 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); 192 require_action_quiet(circle, fail, success = false); 193 194 CFStringRef circleName = SOSCircleGetName(circle); 195 CFDictionaryAddValue(account->circles, circleName, circle); 196 197 if (fullPeerInfoData) { 198 SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); 199 require_action_quiet(full_peer, fail, success = false); 200 201 CFDictionaryAddValue(account->circle_identities, circleName, full_peer); 202 CFReleaseSafe(full_peer); 203 } 204 fail: 205 CFReleaseNull(circle); 206 } 207 } 208 } 209 }); 210 CFReleaseNull(array); 211 212 require_quiet(success, fail); 213 require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, 214 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); 215 216 return account; 217 218fail: 219 // Create a default error if we don't have one: 220 account->factory = NULL; // give the factory back. 221 CFReleaseNull(account); 222 // Try the der inflater from the previous release. 223 account = SOSAccountCreateFromDER_V1(allocator, factory, error, &dersave, derend); 224 if(account) account->departure_code = kSOSNeverAppliedToCircle; 225 return account; 226} 227 228static void SOSAccountConvertKVSDictionaryToRetirementDictionary(SOSAccountRef account) 229{ 230 CFMutableDictionaryRef old_retired_peers = account->retired_peers; 231 account->retired_peers = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); 232 233 CFDictionaryForEach(old_retired_peers, ^(const void *key, const void *value) { 234 if (isDictionary(value)) { 235 CFDictionaryAddValue(account->retired_peers, key, value); 236 } else if (isString(key) && isData(value)) { 237 CFDataRef retired_peer_data = (CFDataRef) value; 238 CFStringRef circle_name = NULL; 239 CFStringRef retired_peer_id = NULL; 240 241 if (kRetirementKey == SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retired_peer_id, NULL)) { 242 CFMutableDictionaryRef circle_retirees = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); 243 244 CFDictionarySetValue(circle_retirees, retired_peer_id, retired_peer_data); 245 } 246 247 CFReleaseSafe(circle_name); 248 CFReleaseSafe(retired_peer_id); 249 } 250 }); 251 CFReleaseSafe(old_retired_peers); 252} 253 254 255#define CURRENT_ACCOUNT_PERSISTENT_VERSION 6 256 257SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, 258 SOSDataSourceFactoryRef factory, 259 CFErrorRef* error, 260 const uint8_t** der_p, const uint8_t *der_end) 261{ 262 SOSAccountRef account = NULL; 263#if UPGRADE_FROM_PREVIOUS_VERSION 264 const uint8_t *dersave = *der_p; 265 const uint8_t *derend = der_end; 266#endif 267 uint64_t version = 0; 268 269 const uint8_t *sequence_end; 270 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); 271 *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); 272 if(!(*der_p) || version < CURRENT_ACCOUNT_PERSISTENT_VERSION) { 273#if UPGRADE_FROM_PREVIOUS_VERSION 274 return SOSAccountCreateFromDER_V3(allocator, factory, error, &dersave, derend); 275#else 276 return NULL; 277#endif 278 } 279 280 { 281 CFDictionaryRef decoded_gestalt = NULL; 282 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, 283 *der_p, der_end); 284 285 if (*der_p == 0) 286 return NULL; 287 288 account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); 289 CFReleaseNull(decoded_gestalt); 290 } 291 292 CFArrayRef array = NULL; 293 *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); 294 295 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; 296 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); 297 *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); 298 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); 299 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->previous_public, error, *der_p, sequence_end); 300 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); 301 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); 302 if (*der_p != sequence_end) 303 *der_p = NULL; 304 account->departure_code = (enum DepartureReason) tmp_departure_code; 305 306 __block bool success = true; 307 308 require_quiet(array && *der_p, fail); 309 310 CFArrayForEach(array, ^(const void *value) { 311 if (success) { 312 if (isString(value)) { 313 CFDictionaryAddValue(account->circles, value, kCFNull); 314 } else { 315 CFDataRef circleData = NULL; 316 CFDataRef fullPeerInfoData = NULL; 317 318 if (isData(value)) { 319 circleData = (CFDataRef) value; 320 } else if (isArray(value)) { 321 CFArrayRef pair = (CFArrayRef) value; 322 323 CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); 324 CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); 325 326 if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { 327 circleData = (CFDataRef) circleObject; 328 fullPeerInfoData = (CFDataRef) fullPeerInfoObject; 329 } 330 } 331 332 if (circleData) { 333 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); 334 require_action_quiet(circle, fail, success = false); 335 336 CFStringRef circleName = SOSCircleGetName(circle); 337 CFDictionaryAddValue(account->circles, circleName, circle); 338 339 if (fullPeerInfoData) { 340 SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); 341 require_action_quiet(full_peer, fail, success = false); 342 343 CFDictionaryAddValue(account->circle_identities, circleName, full_peer); 344 CFReleaseNull(full_peer); 345 } 346 fail: 347 CFReleaseNull(circle); 348 } 349 } 350 } 351 }); 352 CFReleaseNull(array); 353 354 require_quiet(success, fail); 355 require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, 356 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); 357 358 SOSAccountConvertKVSDictionaryToRetirementDictionary(account); 359 360 return account; 361 362fail: 363 account->factory = NULL; // give the factory back. 364 CFReleaseNull(account); 365 return NULL; 366} 367 368 369SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, 370 SOSDataSourceFactoryRef factory, 371 CFErrorRef* error, 372 const uint8_t** der_p, const uint8_t *der_end) 373{ 374 SOSAccountRef account = NULL; 375 uint64_t version = 0; 376 377 const uint8_t *sequence_end; 378 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); 379 *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); 380 if(!(*der_p) || version != 3) { 381 // In this case we want to silently fail so that an account gets newly created. 382 return NULL; 383 } 384 385 { 386 CFDictionaryRef decoded_gestalt = NULL; 387 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, 388 *der_p, der_end); 389 390 if (*der_p == 0) 391 return NULL; 392 393 account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); 394 CFReleaseNull(decoded_gestalt); 395 } 396 397 CFArrayRef array = NULL; 398 *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); 399 400 uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; 401 *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); 402 *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); 403 *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); 404 *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); 405 *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); 406 if (*der_p != sequence_end) 407 *der_p = NULL; 408 account->departure_code = (enum DepartureReason) tmp_departure_code; 409 410 __block bool success = true; 411 412 require_quiet(array && *der_p, fail); 413 414 CFArrayForEach(array, ^(const void *value) { 415 if (success) { 416 if (isString(value)) { 417 CFDictionaryAddValue(account->circles, value, kCFNull); 418 } else { 419 CFDataRef circleData = NULL; 420 CFDataRef fullPeerInfoData = NULL; 421 422 if (isData(value)) { 423 circleData = (CFDataRef) value; 424 } else if (isArray(value)) { 425 CFArrayRef pair = (CFArrayRef) value; 426 427 CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); 428 CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); 429 430 if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { 431 circleData = (CFDataRef) circleObject; 432 fullPeerInfoData = (CFDataRef) fullPeerInfoObject; 433 } 434 } 435 436 if (circleData) { 437 SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); 438 require_action_quiet(circle, fail, success = false); 439 440 CFStringRef circleName = SOSCircleGetName(circle); 441 CFDictionaryAddValue(account->circles, circleName, circle); 442 443 if (fullPeerInfoData) { 444 SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); 445 require_action_quiet(full_peer, fail, success = false); 446 447 CFDictionaryAddValue(account->circle_identities, circleName, full_peer); 448 CFReleaseNull(full_peer); 449 } 450 fail: 451 CFReleaseNull(circle); 452 } 453 } 454 } 455 }); 456 CFReleaseNull(array); 457 458 require_quiet(success, fail); 459 require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, 460 SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); 461 462 SOSAccountConvertKVSDictionaryToRetirementDictionary(account); 463 464 return account; 465 466fail: 467 // Create a default error if we don't have one: 468 account->factory = NULL; // give the factory back. 469 CFReleaseNull(account); 470 // Don't try the der inflater from the previous release. 471 // account = SOSAccountCreateFromDER_V2(allocator, transport, factory, error, &dersave, derend); 472 if(account) account->departure_code = kSOSNeverAppliedToCircle; 473 return account; 474} 475 476SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, 477 SOSDataSourceFactoryRef factory, 478 CFErrorRef* error) 479{ 480 size_t size = CFDataGetLength(circleData); 481 const uint8_t *der = CFDataGetBytePtr(circleData); 482 SOSAccountRef account = SOSAccountCreateFromDER(allocator, factory, 483 error, 484 &der, der + size); 485 return account; 486} 487 488static CFMutableArrayRef SOSAccountCopyCircleArrayToEncode(SOSAccountRef account) 489{ 490 CFMutableArrayRef arrayToEncode = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 491 492 CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { 493 if (isNull(value)) { 494 CFArrayAppendValue(arrayToEncode, key); // Encode the name of the circle that's out of date. 495 } else { 496 SOSCircleRef circle = (SOSCircleRef) value; 497 CFDataRef encodedCircle = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, NULL); 498 CFTypeRef arrayEntry = encodedCircle; 499 CFRetainSafe(arrayEntry); 500 501 SOSFullPeerInfoRef full_peer = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, key); 502 503 if (full_peer) { 504 CFDataRef encodedPeer = SOSFullPeerInfoCopyEncodedData(full_peer, kCFAllocatorDefault, NULL); 505 CFTypeRef originalArrayEntry = arrayEntry; 506 arrayEntry = CFArrayCreateForCFTypes(kCFAllocatorDefault, encodedCircle, encodedPeer, NULL); 507 508 CFReleaseSafe(originalArrayEntry); 509 CFReleaseNull(encodedPeer); 510 } 511 512 CFArrayAppendValue(arrayToEncode, arrayEntry); 513 514 CFReleaseSafe(arrayEntry); 515 CFReleaseNull(encodedCircle); 516 } 517 518 }); 519 520 return arrayToEncode; 521} 522 523size_t SOSAccountGetDEREncodedSize(SOSAccountRef account, CFErrorRef *error) 524{ 525 size_t sequence_size = 0; 526 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 527 uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; 528 529 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); 530 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); 531 require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); 532 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); 533 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); 534 require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); 535 require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->previous_public, error)), fail); 536 require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); 537 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); 538 539 CFReleaseNull(arrayToEncode); 540 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); 541 542fail: 543 CFReleaseNull(arrayToEncode); 544 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); 545 return 0; 546} 547 548uint8_t* SOSAccountEncodeToDER(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) 549{ 550 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 551 uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; 552 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, 553 ccder_encode_uint64(version, der, 554 der_encode_dictionary(account->gestalt, error, der, 555 der_encode_array(arrayToEncode, error, der, 556 ccder_encode_uint64(account->departure_code, der, 557 ccder_encode_bool(account->user_public_trusted, der, 558 der_encode_public_bytes(account->user_public, error, der, 559 der_encode_public_bytes(account->previous_public, error, der, 560 der_encode_data_or_null(account->user_key_parameters, error, der, 561 der_encode_dictionary(account->retired_peers, error, der, der_end)))))))))); 562 563 CFReleaseNull(arrayToEncode); 564 565 return der_end; 566} 567 568 569 570size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account, CFErrorRef *error) 571{ 572 size_t sequence_size = 0; 573 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 574 uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; 575 576 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); 577 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); 578 require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); 579 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); 580 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); 581 require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); 582 require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); 583 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); 584 585 CFReleaseNull(arrayToEncode); 586 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); 587 588fail: 589 CFReleaseNull(arrayToEncode); 590 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); 591 return 0; 592} 593 594uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) 595{ 596 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 597 uint64_t version = 3; 598 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, 599 ccder_encode_uint64(version, der, 600 der_encode_dictionary(account->gestalt, error, der, 601 der_encode_array(arrayToEncode, error, der, 602 ccder_encode_uint64(account->departure_code, der, 603 ccder_encode_bool(account->user_public_trusted, der, 604 der_encode_public_bytes(account->user_public, error, der, 605 der_encode_data_or_null(account->user_key_parameters, error, der, 606 der_encode_dictionary(account->retired_peers, error, der, der_end))))))))); 607 608 CFReleaseNull(arrayToEncode); 609 610 return der_end; 611} 612 613/* Original V2 encoders */ 614 615size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account, CFErrorRef *error) 616{ 617 size_t sequence_size = 0; 618 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 619 620 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); 621 require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); 622 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); 623 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); 624 require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); 625 require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); 626 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); 627 628 CFReleaseNull(arrayToEncode); 629 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); 630 631fail: 632 CFReleaseNull(arrayToEncode); 633 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); 634 return 0; 635} 636 637uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) 638{ 639 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 640 641 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, 642 der_encode_dictionary(account->gestalt, error, der, 643 der_encode_array(arrayToEncode, error, der, 644 ccder_encode_uint64(account->departure_code, der, 645 ccder_encode_bool(account->user_public_trusted, der, 646 der_encode_public_bytes(account->user_public, error, der, 647 der_encode_data_or_null(account->user_key_parameters, error, der, 648 der_encode_dictionary(account->retired_peers, error, der, der_end)))))))); 649 650 CFReleaseNull(arrayToEncode); 651 652 return der_end; 653} 654 655 656/* Original V1 encoders */ 657 658 659size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account, CFErrorRef *error) 660{ 661 size_t sequence_size = 0; 662 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 663 664 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); 665 require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); 666 require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); 667 require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); 668 require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); 669 require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); 670 671 CFReleaseNull(arrayToEncode); 672 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); 673 674fail: 675 CFReleaseNull(arrayToEncode); 676 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); 677 return 0; 678} 679 680uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) 681{ 682 CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); 683 684 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, 685 der_encode_dictionary(account->gestalt, error, der, 686 der_encode_array(arrayToEncode, error, der, 687 ccder_encode_bool(account->user_public_trusted, der, 688 der_encode_public_bytes(account->user_public, error, der, 689 der_encode_data_or_null(account->user_key_parameters, error, der, 690 der_encode_dictionary(account->retired_peers, error, der, der_end))))))); 691 692 CFReleaseNull(arrayToEncode); 693 694 return der_end; 695} 696 697/************************/ 698 699CFDataRef SOSAccountCopyEncodedData(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef *error) 700{ 701 size_t size = SOSAccountGetDEREncodedSize(account, error); 702 if (size == 0) 703 return NULL; 704 uint8_t buffer[size]; 705 uint8_t* start = SOSAccountEncodeToDER(account, error, buffer, buffer + sizeof(buffer)); 706 CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); 707 return result; 708} 709 710