]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c
Security-57337.20.44.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 bool SOSFullPeerInfoAddEscrowRecord(SOSFullPeerInfoRef peer, CFStringRef dsid, CFDictionaryRef escrowRecord, CFErrorRef* error)
287 {
288 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
289 return SOSPeerInfoCopyWithEscrowRecordUpdate(kCFAllocatorDefault, peer, dsid, escrowRecord, key, error);
290 });
291 }
292
293 bool SOSFullPeerInfoReplaceEscrowRecords(SOSFullPeerInfoRef peer, CFDictionaryRef escrowRecords, CFErrorRef* error)
294 {
295 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
296 return SOSPeerInfoCopyWithReplacedEscrowRecords(kCFAllocatorDefault, peer, escrowRecords, key, error);
297 });
298 }
299
300 SOSViewResultCode SOSFullPeerInfoUpdateViews(SOSFullPeerInfoRef peer, SOSViewActionCode action, CFStringRef viewname, CFErrorRef* error)
301 {
302 __block SOSViewResultCode retval = kSOSCCGeneralViewError;
303
304 return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
305 return SOSPeerInfoCopyWithViewsChange(kCFAllocatorDefault, peer, action, viewname, &retval, key, error);
306 }) ? retval : kSOSCCGeneralViewError;
307 }
308
309 static CFMutableSetRef SOSFullPeerInfoCopyViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
310 CFSetRef enabledViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
311 CFMutableSetRef newViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
312
313 if (isSet(minimumViews)) {
314 CFSetUnion(newViews, minimumViews);
315 }
316 if (isSet(excludedViews)) {
317 CFSetSubtract(newViews, excludedViews);
318 }
319
320 if (CFEqualSafe(newViews, enabledViews)) {
321 CFReleaseNull(newViews);
322 }
323
324 CFReleaseNull(enabledViews);
325 return newViews;
326 }
327
328 static bool SOSFullPeerInfoNeedsViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
329 CFSetRef updatedViews = SOSFullPeerInfoCopyViewUpdate(peer, minimumViews, excludedViews);
330 bool needsUpdate = (updatedViews != NULL);
331 CFReleaseNull(updatedViews);
332 return needsUpdate;
333 }
334
335 static bool sosFullPeerInfoRequiresUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
336
337 if(!SOSPeerInfoVersionIsCurrent(peer->peer_info)) return true;
338 if(!SOSPeerInfoSerialNumberIsSet(peer->peer_info)) return true;
339 if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sDeviceID)))return true;
340 if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sTransportType))) return true;
341 if(!(SOSPeerInfoV2DictionaryHasBoolean(peer->peer_info, sPreferIDS))) return true;
342 if(SOSFullPeerInfoNeedsViewUpdate(peer, minimumViews, excludedViews)) return true;
343
344 return false;
345 }
346
347 // Returning false indicates we don't need to upgrade.
348 bool SOSFullPeerInfoUpdateToCurrent(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
349 bool success = false;
350
351 CFMutableSetRef newViews = NULL;
352 CFErrorRef copyError = NULL;
353 CFErrorRef createError = NULL;
354 SecKeyRef device_key = NULL;
355
356 require_quiet(sosFullPeerInfoRequiresUpdate(peer, minimumViews, excludedViews), errOut);
357
358 newViews = SOSFullPeerInfoCopyViewUpdate(peer, minimumViews, excludedViews);
359
360 device_key = SOSFullPeerInfoCopyDeviceKey(peer, &copyError);
361 require_action_quiet(device_key, errOut,
362 secnotice("upgrade", "SOSFullPeerInfoCopyDeviceKey failed: %@", copyError));
363
364 SOSPeerInfoRef newPeer = SOSPeerInfoCreateCurrentCopy(kCFAllocatorDefault, peer->peer_info,
365 NULL, NULL, NULL, newViews,
366 device_key, &createError);
367 require_action_quiet(newPeer, errOut,
368 secnotice("upgrade", "Peer info v2 create copy failed: %@", createError));
369
370 CFTransferRetained(peer->peer_info, newPeer);
371
372 success = true;
373
374 errOut:
375 CFReleaseNull(newViews);
376 CFReleaseNull(copyError);
377 CFReleaseNull(createError);
378 CFReleaseNull(device_key);
379 return success;
380 }
381
382 SOSViewResultCode SOSFullPeerInfoViewStatus(SOSFullPeerInfoRef peer, CFStringRef viewname, CFErrorRef *error)
383 {
384 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(peer);
385 secnotice("views", "have pi %s", (pi)? "true": "false");
386 if(!pi) return kSOSCCGeneralViewError;
387 return SOSPeerInfoViewStatus(pi, viewname, error);
388 }
389
390
391 SOSSecurityPropertyResultCode SOSFullPeerInfoUpdateSecurityProperty(SOSFullPeerInfoRef peer, SOSViewActionCode action, CFStringRef property, CFErrorRef* error)
392 {
393 SOSSecurityPropertyResultCode retval = kSOSCCGeneralSecurityPropertyError;
394 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
395 require_quiet(device_key, fail);
396
397 SOSPeerInfoRef newPeer = SOSPeerInfoCopyWithSecurityPropertyChange(kCFAllocatorDefault, peer->peer_info, action, property, &retval, device_key, error);
398
399 require_quiet(newPeer, fail);
400
401 CFReleaseNull(peer->peer_info);
402 peer->peer_info = newPeer;
403 newPeer = NULL;
404
405 fail:
406 CFReleaseNull(device_key);
407 return retval;
408 }
409
410 SOSSecurityPropertyResultCode SOSFullPeerInfoSecurityPropertyStatus(SOSFullPeerInfoRef peer, CFStringRef property, CFErrorRef *error)
411 {
412 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(peer);
413 secnotice("secprop", "have pi %s", (pi)? "true": "false");
414 if(!pi) return kSOSCCGeneralSecurityPropertyError;
415 return SOSPeerInfoSecurityPropertyStatus(pi, property, error);
416 }
417
418
419 SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer) {
420 return fullPeer?fullPeer->peer_info:NULL;
421 }
422
423 // MARK: Private Key Retrieval and Existence
424
425 static SecKeyRef SOSFullPeerInfoCopyPubKey(SOSFullPeerInfoRef fpi) {
426 SecKeyRef retval = NULL;
427 require_quiet(fpi, errOut);
428 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi);
429 require_quiet(pi, errOut);
430 retval = SOSPeerInfoCopyPubKey(pi);
431
432 errOut:
433 return retval;
434 }
435
436 static SecKeyRef SOSFullPeerInfoCopyMatchingPrivateKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
437 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
438 SecKeyRef retval = SecKeyCopyMatchingPrivateKey(pub, error);
439 CFReleaseNull(pub);
440 return retval;
441 }
442
443 static OSStatus SOSFullPeerInfoGetMatchingPrivateKeyStatus(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
444 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
445 OSStatus retval = SecKeyGetMatchingPrivateKeyStatus(pub, error);
446 CFReleaseNull(pub);
447 return retval;
448 }
449
450 bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error) {
451 OSStatus result = SOSFullPeerInfoGetMatchingPrivateKeyStatus(peer, error);
452 if(result == errSecSuccess) return true;
453 return false;
454 }
455
456 bool SOSFullPeerInfoPrivKeyExists(SOSFullPeerInfoRef peer) {
457 OSStatus result = SOSFullPeerInfoGetMatchingPrivateKeyStatus(peer, NULL);
458 if(result == errSecItemNotFound || result == errSecParam) return false;
459 return true;
460 }
461
462 bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fpi, CFErrorRef* error) {
463 SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
464 CFDictionaryRef privQuery = CreatePrivateKeyMatchingQuery(pub, false);
465 CFMutableDictionaryRef query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, privQuery);
466 CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanFalse);
467 SecItemDelete(query);
468 CFReleaseNull(privQuery);
469 CFReleaseNull(query);
470 CFReleaseNull(pub);
471 return true;
472 }
473
474 SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error) {
475 return SOSFullPeerInfoCopyMatchingPrivateKey(fullPeer, error);
476 }
477
478 //
479 // MARK: Encode and decode
480 //
481 size_t SOSFullPeerInfoGetDEREncodedSize(SOSFullPeerInfoRef peer, CFErrorRef *error)
482 {
483 size_t peer_size = SOSPeerInfoGetDEREncodedSize(peer->peer_info, error);
484 if (peer_size == 0)
485 return 0;
486
487 size_t ref_size = der_sizeof_data(peer->key_ref, error);
488 if (ref_size == 0)
489 return 0;
490
491 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
492 peer_size + ref_size);
493 }
494
495 uint8_t* SOSFullPeerInfoEncodeToDER(SOSFullPeerInfoRef peer, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
496 {
497 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
498 SOSPeerInfoEncodeToDER(peer->peer_info, error, der,
499 der_encode_data(peer->key_ref, error, der, der_end)));
500 }
501
502 CFDataRef SOSFullPeerInfoCopyEncodedData(SOSFullPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error)
503 {
504 size_t size = SOSFullPeerInfoGetDEREncodedSize(peer, error);
505 if (size == 0)
506 return NULL;
507 uint8_t buffer[size];
508 uint8_t* start = SOSFullPeerInfoEncodeToDER(peer, error, buffer, buffer + sizeof(buffer));
509 CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size);
510 return result;
511 }
512
513 bool SOSFullPeerInfoPromoteToApplication(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
514 {
515 bool success = false;
516 SOSPeerInfoRef old_pi = NULL;
517
518 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
519 require_quiet(device_key, exit);
520
521 old_pi = fpi->peer_info;
522 fpi->peer_info = SOSPeerInfoCopyAsApplication(old_pi, user_key, device_key, error);
523
524 require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
525
526 success = true;
527
528 exit:
529 CFReleaseSafe(old_pi);
530 CFReleaseSafe(device_key);
531 return success;
532 }
533
534 bool SOSFullPeerInfoUpgradeSignatures(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
535 {
536 bool success = false;
537 SOSPeerInfoRef old_pi = NULL;
538
539 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
540 require_quiet(device_key, exit);
541
542 old_pi = fpi->peer_info;
543 fpi->peer_info = SOSPeerInfoUpgradeSignatures(NULL, user_key, device_key, old_pi, error);
544
545 require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
546
547 success = true;
548
549 exit:
550 CFReleaseSafe(old_pi);
551 CFReleaseSafe(device_key);
552 return success;
553 }
554
555 //
556 //
557 //
558
559 SOSPeerInfoRef SOSFullPeerInfoPromoteToRetiredAndCopy(SOSFullPeerInfoRef fpi, CFErrorRef *error)
560 {
561 SOSPeerInfoRef peer_to_free = NULL;
562 SOSPeerInfoRef retired_peer = NULL;
563 SecKeyRef key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
564 require_quiet(key, error_out);
565
566 retired_peer = SOSPeerInfoCreateRetirementTicket(NULL, key, fpi->peer_info, error);
567
568 require_quiet(retired_peer, error_out);
569
570 peer_to_free = fpi->peer_info;
571 fpi->peer_info = retired_peer;
572 CFRetainSafe(fpi->peer_info);
573
574 error_out:
575 CFReleaseNull(key);
576 CFReleaseNull(peer_to_free);
577 return retired_peer;
578 }
579
580
581 bool SOSFullPeerInfoPing(SOSFullPeerInfoRef peer, CFErrorRef* error) {
582 bool retval = false;
583 SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
584 require_quiet(device_key, fail);
585 SOSPeerInfoRef newPeer = SOSPeerInfoCopyWithPing(kCFAllocatorDefault, peer->peer_info, device_key, error);
586 require_quiet(newPeer, fail);
587
588 CFReleaseNull(peer->peer_info);
589 peer->peer_info = newPeer;
590 newPeer = NULL;
591 retval = true;
592 fail:
593 CFReleaseNull(device_key);
594 return retval;
595 }
596
597