]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSFullPeerInfo.c
1 /*
2 * Copyright (c) 2012-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 <AssertMacros.h>
26
27 #include <Security/SecureObjectSync/SOSFullPeerInfo.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
29
30 #include <Security/SecureObjectSync/SOSCircle.h>
31
32 #include <Security/SecureObjectSync/SOSInternal.h>
33 #include <Security/SecureObjectSync/SOSAccountPriv.h>
34
35 #include <Security/SecKeyPriv.h>
36 #include <Security/SecItemPriv.h>
37 #include <Security/SecOTR.h>
38 #include <CoreFoundation/CFArray.h>
39 #include <dispatch/dispatch.h>
40 #include <SOSPeerInfoDER.h>
41 #include <Security/SecFramework.h>
42
43 #include <stdlib.h>
44 #include <assert.h>
45
46 #include <utilities/SecCFWrappers.h>
47 #include <utilities/SecCFRelease.h>
48
49 #include <utilities/der_plist.h>
50 #include <utilities/der_plist_internal.h>
51 #include <corecrypto/ccder.h>
52
53 #include <CommonCrypto/CommonDigest.h>
54 #include <CommonCrypto/CommonDigestSPI.h>
55
56 #include <CoreFoundation/CoreFoundation.h>
57
58 #include "utilities/iOSforOSX.h"
59
60 #include <AssertMacros.h>
61
62 #include <utilities/SecCFError.h>
63
64 // for OS X
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68
69 //---- missing
70
71 extern OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes);
72 extern SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey);
73 #ifdef __cplusplus
74 }
75 #endif
76
77 struct __OpaqueSOSFullPeerInfo {
78 CFRuntimeBase _base;
79
80 SOSPeerInfoRef peer_info;
81 CFDataRef key_ref;
82 };
83
84 CFGiblisWithHashFor(SOSFullPeerInfo);
85
86
87 static CFStringRef sPublicKeyKey = CFSTR("PublicSigningKey");
88
89 CFStringRef kSOSFullPeerInfoDescriptionKey = CFSTR("SOSFullPeerInfoDescription");
90 CFStringRef kSOSFullPeerInfoSignatureKey = CFSTR("SOSFullPeerInfoSignature");
91 CFStringRef kSOSFullPeerInfoNameKey = CFSTR("SOSFullPeerInfoName");
92
93
94 static bool SOSFullPeerInfoUpdate(SOSFullPeerInfoRef peer, CFErrorRef *error, SOSPeerInfoRef (^create_modification)(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error)) {
95 bool result = false;
96
97 SOSPeerInfoRef newPeer = NULL;
98 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
99 require_quiet(device_key, fail);
100
101 newPeer = create_modification(peer->peer_info, device_key, error);
102 require_quiet(newPeer, fail);
103
104 CFTransferRetained(peer->peer_info, newPeer);
105
106 result = true;
107
108 fail:
109 CFReleaseNull(device_key);
110 CFReleaseNull(newPeer);
111 return result;
112 }
113
114 bool SOSFullPeerInfoUpdateToThisPeer(SOSFullPeerInfoRef peer, SOSPeerInfoRef pi, CFErrorRef *error) {
115 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
116 return SOSPeerInfoSign(key, pi, error) ? pi: NULL;
117 });
118 }
119
120 SOSFullPeerInfoRef SOSFullPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt,
121 CFDataRef backupKey, SecKeyRef signingKey,
122 CFErrorRef* error) {
123 return SOSFullPeerInfoCreateWithViews(allocator, gestalt, backupKey, NULL, signingKey, error);
124 }
125
126 SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator,
127 CFDictionaryRef gestalt, CFDataRef backupKey, CFSetRef initialViews,
128 SecKeyRef signingKey, CFErrorRef* error) {
129
130 SOSFullPeerInfoRef result = NULL;
131 SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
132
133 bool useIDS = whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture;
134
135 CFStringRef transportType = useIDS ? SOSTransportMessageTypeIDS : SOSTransportMessageTypeKVS;
136 CFBooleanRef preferIDS = useIDS ? kCFBooleanTrue : kCFBooleanFalse;
137 CFStringRef IDSID = CFSTR("");
138
139 fpi->peer_info = SOSPeerInfoCreateWithTransportAndViews(allocator, gestalt, backupKey,
140 IDSID, transportType, preferIDS,
141 initialViews,
142 signingKey, error);
143 require_quiet(fpi->peer_info, exit);
144
145 OSStatus status = SecKeyCopyPersistentRef(signingKey, &fpi->key_ref);
146 require_quiet(SecError(status, error, CFSTR("Inflating persistent ref")), exit);
147
148 CFTransferRetained(result, fpi);
149
150 exit:
151 CFReleaseNull(fpi);
152 return result;
153 }
154
155 bool SOSFullPeerInfoUpdateTransportType(SOSFullPeerInfoRef peer, CFStringRef transportType, CFErrorRef* error)
156 {
157 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
158 return SOSPeerInfoSetTransportType(kCFAllocatorDefault, peer, transportType, key, error);
159 });
160 }
161
162 bool SOSFullPeerInfoUpdateDeviceID(SOSFullPeerInfoRef peer, CFStringRef deviceID, CFErrorRef* error){
163 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
164 return SOSPeerInfoSetDeviceID(kCFAllocatorDefault, peer, deviceID, key, error);
165 });
166 }
167
168 bool SOSFullPeerInfoUpdateTransportPreference(SOSFullPeerInfoRef peer, CFBooleanRef preference, CFErrorRef* error){
169 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
170 return SOSPeerInfoSetIDSPreference(kCFAllocatorDefault, peer, preference, key, error);
171 });
172 }
173
174 SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error) {
175 SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
176
177 SecKeyRef pubKey = NULL;
178
179 fpi->peer_info = peer;
180 CFRetainSafe(fpi->peer_info);
181 if (fpi->peer_info == NULL) {
182 CFReleaseNull(fpi);
183 goto exit;
184 }
185
186 pubKey = SOSPeerInfoCopyPubKey(peer);
187
188 fpi->key_ref = SecKeyCreatePersistentRefToMatchingPrivateKey(pubKey, error);
189
190 if (fpi->key_ref == NULL) {
191 CFReleaseNull(fpi);
192 goto exit;
193 }
194
195 exit:
196 CFReleaseNull(pubKey);
197 return fpi;
198 }
199
200
201 SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
202 const uint8_t** der_p, const uint8_t *der_end) {
203 SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
204
205 const uint8_t *sequence_end;
206
207 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
208 CFReleaseNull(fpi->peer_info);
209 fpi->peer_info = SOSPeerInfoCreateFromDER(allocator, error, der_p, der_end);
210 require_quiet(fpi->peer_info != NULL, fail);
211
212 *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end);
213 require_quiet(*der_p != NULL, fail);
214
215 return fpi;
216
217 fail:
218 CFReleaseNull(fpi);
219 return NULL;
220 }
221
222 SOSFullPeerInfoRef SOSFullPeerInfoCreateFromData(CFAllocatorRef allocator, CFDataRef fullPeerData, CFErrorRef *error)
223 {
224 if(!fullPeerData) return NULL;
225 size_t size = CFDataGetLength(fullPeerData);
226 const uint8_t *der = CFDataGetBytePtr(fullPeerData);
227 SOSFullPeerInfoRef inflated = SOSFullPeerInfoCreateFromDER(allocator, error, &der, der + size);
228 return inflated;
229 }
230
231 static void SOSFullPeerInfoDestroy(CFTypeRef aObj) {
232 SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) aObj;
233
234 CFReleaseNull(fpi->peer_info);
235 CFReleaseNull(fpi->key_ref);
236 }
237
238 static Boolean SOSFullPeerInfoCompare(CFTypeRef lhs, CFTypeRef rhs) {
239 SOSFullPeerInfoRef lpeer = (SOSFullPeerInfoRef) lhs;
240 SOSFullPeerInfoRef rpeer = (SOSFullPeerInfoRef) rhs;
241
242 if (!CFEqual(lpeer->peer_info, rpeer->peer_info))
243 return false;
244
245 if (CFEqual(lpeer->key_ref, rpeer->key_ref))
246 return true;
247
248 SecKeyRef lpk = SOSFullPeerInfoCopyDeviceKey(lpeer, NULL);
249 SecKeyRef rpk = SOSFullPeerInfoCopyDeviceKey(rpeer, NULL);
250
251 bool match = lpk && rpk && CFEqual(lpk, rpk);
252
253 CFReleaseNull(lpk);
254 CFReleaseNull(rpk);
255
256 return match;
257 }
258
259 static CFHashCode SOSFullPeerInfoHash(CFTypeRef cf) {
260 SOSFullPeerInfoRef peer = (SOSFullPeerInfoRef) cf;
261
262 return CFHash(peer->peer_info);
263 }
264
265 static CFStringRef SOSFullPeerInfoCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOptions) {
266 SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) aObj;
267
268 return CFStringCreateWithFormat(NULL, NULL, CFSTR("<SOSFullPeerInfo@%p: \"%@\">"), fpi, fpi->peer_info);
269 }
270
271 bool SOSFullPeerInfoUpdateGestalt(SOSFullPeerInfoRef peer, CFDictionaryRef gestalt, CFErrorRef* error)
272 {
273 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
274 return SOSPeerInfoCopyWithGestaltUpdate(kCFAllocatorDefault, peer,
275 gestalt, key, error);
276 });
277 }
278
279 bool SOSFullPeerInfoUpdateBackupKey(SOSFullPeerInfoRef peer, CFDataRef backupKey, CFErrorRef* error)
280 {
281 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
282 return SOSPeerInfoCopyWithBackupKeyUpdate(kCFAllocatorDefault, peer, backupKey, key, error);
283 });
284 }
285
286 SOSViewResultCode SOSFullPeerInfoUpdateViews(SOSFullPeerInfoRef peer, SOSViewActionCode action, CFStringRef viewname, CFErrorRef* error)
287 {
288 __block SOSViewResultCode retval = kSOSCCGeneralViewError;
289
290 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
291 return SOSPeerInfoCopyWithViewsChange(kCFAllocatorDefault, peer, action, viewname, &retval, key, error);
292 }) ? retval : kSOSCCGeneralViewError;
293 }
294
295
296 static bool CFSetIsSubset(CFSetRef smaller, CFSetRef bigger) {
297 __block bool isSubset = true;
298 CFSetForEach(smaller, ^(const void *value) {
299 if (!CFSetContainsValue(bigger, value)) {
300 isSubset = false;
301 }
302 });
303
304 return isSubset;
305 }
306
307 static void CFSetUnionSet(CFMutableSetRef target, CFSetRef source) {
308 CFSetForEach(source, ^(const void *value) {
309 CFSetAddValue(target, value);
310 });
311 }
312
313 static bool sosFullPeerInfoNeedsViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
314 CFSetRef currentViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
315 bool success = isSet(minimumViews) && (!isSet(currentViews) || !CFSetIsSubset(minimumViews, currentViews));
316 CFReleaseNull(currentViews);
317 return success;
318 }
319
320 static bool sosFullPeerInfoRequiresUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
321
322 if(!SOSPeerInfoVersionIsCurrent(peer->peer_info)) return true;
323 if(!SOSPeerInfoSerialNumberIsSet(peer->peer_info)) return true;
324 if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sDeviceID)))return true;
325 if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sTransportType))) return true;
326 if(!(SOSPeerInfoV2DictionaryHasBoolean(peer->peer_info, sPreferIDS))) return true;
327 if(sosFullPeerInfoNeedsViewUpdate(peer, minimumViews)) return true;
328
329 return false;
330 }
331
332 // Returning false indicates we don't need to upgrade.
333 bool SOSFullPeerInfoUpdateToCurrent(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
334 CFMutableSetRef newViews = NULL;
335
336 if(!sosFullPeerInfoRequiresUpdate(peer, minimumViews)) return false;
337
338 CFSetRef currentViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
339 if (sosFullPeerInfoNeedsViewUpdate(peer, minimumViews)) {
340 newViews = isSet(currentViews) ? CFSetCreateMutableCopy(kCFAllocatorDefault, 0, currentViews) : CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
341 CFSetUnionSet(newViews, minimumViews);
342 }
343
344 CFErrorRef copyError = NULL;
345 CFErrorRef createError = NULL;
346 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, &copyError);
347 require_action_quiet(device_key, errOut,
348 secnotice("upgrade", "SOSFullPeerInfoCopyDeviceKey failed: %@", copyError));
349
350 SOSPeerInfoRef newPeer = SOSPeerInfoCreateCurrentCopy(kCFAllocatorDefault, peer->peer_info,
351 NULL, NULL, NULL, newViews ? newViews : minimumViews,
352 device_key, &createError);
353 require_action_quiet(newPeer, errOut,
354 secnotice("upgrade", "Peer info v2 create copy failed: %@", createError));
355
356 CFTransferRetained(peer->peer_info, newPeer);
357
358 CFReleaseNull(currentViews);
359 CFReleaseSafe(newViews);
360 CFReleaseNull(device_key);
361 return true;
362
363 errOut:
364 CFReleaseNull(currentViews);
365 CFReleaseSafe(newViews);
366 CFReleaseNull(copyError);
367 CFReleaseNull(createError);
368 CFReleaseNull(device_key);
369 return false;
370 }
371
372 SOSViewResultCode SOSFullPeerInfoViewStatus(SOSFullPeerInfoRef peer, CFStringRef viewname, CFErrorRef *error)
373 {
374 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(peer);
375 secnotice("views", "have pi %s", (pi)? "true": "false");
376 if(!pi) return kSOSCCGeneralViewError;
377 return SOSPeerInfoViewStatus(pi, viewname, error);
378 }
379
380
381 SOSSecurityPropertyResultCode SOSFullPeerInfoUpdateSecurityProperty(SOSFullPeerInfoRef peer, SOSViewActionCode action, CFStringRef property, CFErrorRef* error)
382 {
383 SOSSecurityPropertyResultCode retval = kSOSCCGeneralSecurityPropertyError;
384 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
385 require_quiet(device_key, fail);
386
387 SOSPeerInfoRef newPeer = SOSPeerInfoCopyWithSecurityPropertyChange(kCFAllocatorDefault, peer->peer_info, action, property, &retval, device_key, error);
388
389 require_quiet(newPeer, fail);
390
391 CFReleaseNull(peer->peer_info);
392 peer->peer_info = newPeer;
393 newPeer = NULL;
394
395 fail:
396 CFReleaseNull(device_key);
397 return retval;
398 }
399
400 SOSSecurityPropertyResultCode SOSFullPeerInfoSecurityPropertyStatus(SOSFullPeerInfoRef peer, CFStringRef property, CFErrorRef *error)
401 {
402 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(peer);
403 secnotice("secprop", "have pi %s", (pi)? "true": "false");
404 if(!pi) return kSOSCCGeneralSecurityPropertyError;
405 return SOSPeerInfoSecurityPropertyStatus(pi, property, error);
406 }
407
408
409 SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer) {
410 return fullPeer?fullPeer->peer_info:NULL;
411 }
412
413 // MARK: Private Key Retrieval and Existence
414
415 static SecKeyRef SOSFullPeerInfoCopyPubKey(SOSFullPeerInfoRef fpi) {
416 SecKeyRef retval = NULL;
417 require_quiet(fpi, errOut);
418 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi);
419 require_quiet(pi, errOut);
420 retval = SOSPeerInfoCopyPubKey(pi);
421
422 errOut:
423 return retval;
424 }
425
426 static SecKeyRef SOSFullPeerInfoCopyMatchingPrivateKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
427 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
428 SecKeyRef retval = SecKeyCopyMatchingPrivateKey(pub, error);
429 CFReleaseNull(pub);
430 return retval;
431 }
432
433 static OSStatus SOSFullPeerInfoGetMatchingPrivateKeyStatus(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
434 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
435 OSStatus retval = SecKeyGetMatchingPrivateKeyStatus(pub, error);
436 CFReleaseNull(pub);
437 return retval;
438 }
439
440 bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error) {
441 OSStatus result = SOSFullPeerInfoGetMatchingPrivateKeyStatus(peer, error);
442 if(result == errSecSuccess) return true;
443 return false;
444 }
445
446 bool SOSFullPeerInfoPrivKeyExists(SOSFullPeerInfoRef peer) {
447 OSStatus result = SOSFullPeerInfoGetMatchingPrivateKeyStatus(peer, NULL);
448 if(result == errSecItemNotFound || result == errSecParam) return false;
449 return true;
450 }
451
452 bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fpi, CFErrorRef* error) {
453 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
454 CFDictionaryRef privQuery = CreatePrivateKeyMatchingQuery(pub, false);
455 CFMutableDictionaryRef query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, privQuery);
456 CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanFalse);
457 SecItemDelete(query);
458 CFReleaseNull(privQuery);
459 CFReleaseNull(query);
460 CFReleaseNull(pub);
461 return true;
462 }
463
464 SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error) {
465 return SOSFullPeerInfoCopyMatchingPrivateKey(fullPeer, error);
466 }
467
468 //
469 // MARK: Encode and decode
470 //
471 size_t SOSFullPeerInfoGetDEREncodedSize(SOSFullPeerInfoRef peer, CFErrorRef *error)
472 {
473 size_t peer_size = SOSPeerInfoGetDEREncodedSize(peer->peer_info, error);
474 if (peer_size == 0)
475 return 0;
476
477 size_t ref_size = der_sizeof_data(peer->key_ref, error);
478 if (ref_size == 0)
479 return 0;
480
481 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
482 peer_size + ref_size);
483 }
484
485 uint8_t* SOSFullPeerInfoEncodeToDER(SOSFullPeerInfoRef peer, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
486 {
487 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
488 SOSPeerInfoEncodeToDER(peer->peer_info, error, der,
489 der_encode_data(peer->key_ref, error, der, der_end)));
490 }
491
492 CFDataRef SOSFullPeerInfoCopyEncodedData(SOSFullPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error)
493 {
494 size_t size = SOSFullPeerInfoGetDEREncodedSize(peer, error);
495 if (size == 0)
496 return NULL;
497 uint8_t buffer[size];
498 uint8_t* start = SOSFullPeerInfoEncodeToDER(peer, error, buffer, buffer + sizeof(buffer));
499 CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size);
500 return result;
501 }
502
503 bool SOSFullPeerInfoPromoteToApplication(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
504 {
505 bool success = false;
506 SOSPeerInfoRef old_pi = NULL;
507
508 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
509 require_quiet(device_key, exit);
510
511 old_pi = fpi->peer_info;
512 fpi->peer_info = SOSPeerInfoCopyAsApplication(old_pi, user_key, device_key, error);
513
514 require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
515
516 success = true;
517
518 exit:
519 CFReleaseSafe(old_pi);
520 CFReleaseSafe(device_key);
521 return success;
522 }
523
524 bool SOSFullPeerInfoUpgradeSignatures(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
525 {
526 bool success = false;
527 SOSPeerInfoRef old_pi = NULL;
528
529 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
530 require_quiet(device_key, exit);
531
532 old_pi = fpi->peer_info;
533 fpi->peer_info = SOSPeerInfoUpgradeSignatures(NULL, user_key, device_key, old_pi, error);
534
535 require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
536
537 success = true;
538
539 exit:
540 CFReleaseSafe(old_pi);
541 CFReleaseSafe(device_key);
542 return success;
543 }
544
545 //
546 //
547 //
548
549 SOSPeerInfoRef SOSFullPeerInfoPromoteToRetiredAndCopy(SOSFullPeerInfoRef fpi, CFErrorRef *error)
550 {
551 SOSPeerInfoRef peer_to_free = NULL;
552 SOSPeerInfoRef retired_peer = NULL;
553 SecKeyRef key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
554 require_quiet(key, error_out);
555
556 retired_peer = SOSPeerInfoCreateRetirementTicket(NULL, key, fpi->peer_info, error);
557
558 require_quiet(retired_peer, error_out);
559
560 peer_to_free = fpi->peer_info;
561 fpi->peer_info = retired_peer;
562 CFRetainSafe(fpi->peer_info);
563
564 error_out:
565 CFReleaseNull(key);
566 CFReleaseNull(peer_to_free);
567 return retired_peer;
568 }
569
570
571 bool SOSFullPeerInfoPing(SOSFullPeerInfoRef peer, CFErrorRef* error) {
572 bool retval = false;
573 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
574 require_quiet(device_key, fail);
575 SOSPeerInfoRef newPeer = SOSPeerInfoCopyWithPing(kCFAllocatorDefault, peer->peer_info, device_key, error);
576 require_quiet(newPeer, fail);
577
578 CFReleaseNull(peer->peer_info);
579 peer->peer_info = newPeer;
580 newPeer = NULL;
581 retval = true;
582 fail:
583 CFReleaseNull(device_key);
584 return retval;
585 }
586
587