+++ /dev/null
-//
-// SOSFullPeerInfo.c
-// sec
-//
-// Created by Mitch Adler on 10/26/12.
-//
-//
-
-#include <AssertMacros.h>
-
-#include <SecureObjectSync/SOSFullPeerInfo.h>
-#include <SecureObjectSync/SOSCircle.h>
-
-#include <SecureObjectSync/SOSInternal.h>
-
-#include <Security/SecKeyPriv.h>
-#include <Security/SecItemPriv.h>
-#include <Security/SecOTR.h>
-#include <CoreFoundation/CFArray.h>
-#include <dispatch/dispatch.h>
-
-#include <stdlib.h>
-#include <assert.h>
-
-#include <utilities/SecCFWrappers.h>
-#include <utilities/SecCFRelease.h>
-
-#include <utilities/der_plist.h>
-#include <utilities/der_plist_internal.h>
-#include <corecrypto/ccder.h>
-
-#include <CommonCrypto/CommonDigest.h>
-#include <CommonCrypto/CommonDigestSPI.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "utilities/iOSforOSX.h"
-
-#include <AssertMacros.h>
-
-#include <utilities/SecCFError.h>
-
-// for OS X
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//---- missing
-
-extern OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes);
-extern SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey);
-#ifdef __cplusplus
-}
-#endif
-
-struct __OpaqueSOSFullPeerInfo {
- CFRuntimeBase _base;
-
- SOSPeerInfoRef peer_info;
- CFDataRef key_ref;
-};
-
-CFGiblisWithHashFor(SOSFullPeerInfo);
-
-
-static CFStringRef sPublicKeyKey = CFSTR("PublicSigningKey");
-static CFStringRef sNameKey = CFSTR("DeviceName");
-static CFStringRef sVersionKey = CFSTR("ConflictVersion");
-
-CFStringRef kSOSFullPeerInfoDescriptionKey = CFSTR("SOSFullPeerInfoDescription");
-CFStringRef kSOSFullPeerInfoSignatureKey = CFSTR("SOSFullPeerInfoSignature");
-CFStringRef kSOSFullPeerInfoNameKey = CFSTR("SOSFullPeerInfoName");
-
-SOSFullPeerInfoRef SOSFullPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error) {
- SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
-
- fpi->peer_info = SOSPeerInfoCreate(allocator, gestalt, signingKey, error);
- if (fpi->peer_info == NULL) {
- CFReleaseNull(fpi);
- goto exit;
- }
-
- OSStatus result = SecKeyCopyPersistentRef(signingKey, &fpi->key_ref);
-
- if (result != errSecSuccess) {
- CFReleaseNull(fpi);
- goto exit;
- }
-
-exit:
- return fpi;
-}
-
-
-
-SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error) {
- SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
-
- SecKeyRef pubKey = NULL;
-
- fpi->peer_info = peer;
- CFRetainSafe(fpi->peer_info);
- if (fpi->peer_info == NULL) {
- CFReleaseNull(fpi);
- goto exit;
- }
-
- pubKey = SOSPeerInfoCopyPubKey(peer);
-
- fpi->key_ref = SecKeyCreatePersistentRefToMatchingPrivateKey(pubKey, error);
-
- if (fpi->key_ref == NULL) {
- CFReleaseNull(fpi);
- goto exit;
- }
-
-exit:
- CFReleaseNull(pubKey);
- return fpi;
-}
-
-
-SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
- const uint8_t** der_p, const uint8_t *der_end) {
- SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
-
- const uint8_t *sequence_end;
-
- *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
-
- fpi->peer_info = SOSPeerInfoCreateFromDER(allocator, error, der_p, der_end);
- require_quiet(fpi->peer_info != NULL, fail);
-
- *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end);
- require_quiet(*der_p != NULL, fail);
-
- return fpi;
-
-fail:
- CFReleaseNull(fpi);
- return NULL;
-}
-
-SOSFullPeerInfoRef SOSFullPeerInfoCreateFromData(CFAllocatorRef allocator, CFDataRef fullPeerData, CFErrorRef *error)
-{
- size_t size = CFDataGetLength(fullPeerData);
- const uint8_t *der = CFDataGetBytePtr(fullPeerData);
- SOSFullPeerInfoRef inflated = SOSFullPeerInfoCreateFromDER(allocator, error, &der, der + size);
- return inflated;
-}
-
-static void SOSFullPeerInfoDestroy(CFTypeRef aObj) {
- SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) aObj;
-
- CFReleaseNull(fpi->peer_info);
- CFReleaseNull(fpi->key_ref);
-}
-
-static Boolean SOSFullPeerInfoCompare(CFTypeRef lhs, CFTypeRef rhs) {
- SOSFullPeerInfoRef lpeer = (SOSFullPeerInfoRef) lhs;
- SOSFullPeerInfoRef rpeer = (SOSFullPeerInfoRef) rhs;
-
- if (!CFEqual(lpeer->peer_info, rpeer->peer_info))
- return false;
-
- if (CFEqual(lpeer->key_ref, rpeer->key_ref))
- return true;
-
- SecKeyRef lpk = SOSFullPeerInfoCopyDeviceKey(lpeer, NULL);
- SecKeyRef rpk = SOSFullPeerInfoCopyDeviceKey(rpeer, NULL);
-
- bool match = lpk && rpk && CFEqual(lpk, rpk);
-
- CFReleaseNull(lpk);
- CFReleaseNull(rpk);
-
- return match;
-}
-
-static CFHashCode SOSFullPeerInfoHash(CFTypeRef cf) {
- SOSFullPeerInfoRef peer = (SOSFullPeerInfoRef) cf;
-
- return CFHash(peer->peer_info);
-}
-
-static CFStringRef SOSFullPeerInfoCopyDescription(CFTypeRef aObj) {
- SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) aObj;
-
- return CFStringCreateWithFormat(NULL, NULL, CFSTR("<SOSFullPeerInfo@%p: \"%@\">"), fpi, fpi->peer_info);
-}
-
-bool SOSFullPeerInfoUpdateGestalt(SOSFullPeerInfoRef peer, CFDictionaryRef gestalt, CFErrorRef* error)
-{
- SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, error);
- require_quiet(device_key, fail);
-
- SOSPeerInfoRef newPeer = SOSPeerInfoCopyWithGestaltUpdate(kCFAllocatorDefault, peer->peer_info,
- gestalt, device_key, error);
-
- require_quiet(newPeer, fail);
-
- CFReleaseNull(peer->peer_info);
- peer->peer_info = newPeer;
- newPeer = NULL;
-
- CFReleaseNull(device_key);
- return true;
-
-fail:
- CFReleaseNull(device_key);
- return false;
-}
-
-
-bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error) {
- return true;
-}
-
-bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error) {
- CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
- kSecValuePersistentRef, fullPeer->key_ref,
- kSecUseTombstones, kCFBooleanFalse,
- NULL);
- SecItemDelete(query);
- CFReleaseNull(query);
-
- return true;
-}
-
-SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer)
-{
- return fullPeer?fullPeer->peer_info:NULL;
-}
-
-SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error)
-{
- SecKeyRef device_key = NULL;
-
- require(fullPeer->key_ref, fail);
-
- OSStatus result = SecKeyFindWithPersistentRef(fullPeer->key_ref, &device_key);
-
- require_action_quiet(result == errSecSuccess, fail, SecError(result, error, CFSTR("Finding Persistent Ref")));
-
- return device_key;
-
-fail:
- CFReleaseNull(device_key);
- return NULL;
-}
-
-//
-// MARK: Encode and decode
-//
-size_t SOSFullPeerInfoGetDEREncodedSize(SOSFullPeerInfoRef peer, CFErrorRef *error)
-{
- size_t peer_size = SOSPeerInfoGetDEREncodedSize(peer->peer_info, error);
- if (peer_size == 0)
- return 0;
-
- size_t ref_size = der_sizeof_data(peer->key_ref, error);
- if (ref_size == 0)
- return 0;
-
- return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
- peer_size + ref_size);
-}
-
-uint8_t* SOSFullPeerInfoEncodeToDER(SOSFullPeerInfoRef peer, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
-{
- return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
- SOSPeerInfoEncodeToDER(peer->peer_info, error, der,
- der_encode_data(peer->key_ref, error, der, der_end)));
-}
-
-CFDataRef SOSFullPeerInfoCopyEncodedData(SOSFullPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error)
-{
- size_t size = SOSFullPeerInfoGetDEREncodedSize(peer, error);
- if (size == 0)
- return NULL;
- uint8_t buffer[size];
- uint8_t* start = SOSFullPeerInfoEncodeToDER(peer, error, buffer, buffer + sizeof(buffer));
- CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size);
- return result;
-}
-
-bool SOSFullPeerInfoPromoteToApplication(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
-{
- bool success = false;
- SOSPeerInfoRef old_pi = NULL;
-
- SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
- require_quiet(device_key, exit);
-
- old_pi = fpi->peer_info;
- fpi->peer_info = SOSPeerInfoCopyAsApplication(old_pi, user_key, device_key, error);
-
- require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
-
- success = true;
-
-exit:
- CFReleaseSafe(old_pi);
- CFReleaseSafe(device_key);
- return success;
-}
-
-bool SOSFullPeerInfoUpgradeSignatures(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error)
-{
- bool success = false;
- SOSPeerInfoRef old_pi = NULL;
-
- SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
- require_quiet(device_key, exit);
-
- old_pi = fpi->peer_info;
- fpi->peer_info = SOSPeerInfoUpgradeSignatures(NULL, user_key, device_key, old_pi, error);
-
- require_action_quiet(fpi->peer_info, exit, fpi->peer_info = old_pi; old_pi = NULL);
-
- success = true;
-
-exit:
- CFReleaseSafe(old_pi);
- CFReleaseSafe(device_key);
- return success;
-}
-
-//
-//
-//
-
-SOSPeerInfoRef SOSFullPeerInfoPromoteToRetiredAndCopy(SOSFullPeerInfoRef fpi, CFErrorRef *error)
-{
- SOSPeerInfoRef peer_to_free = NULL;
- SOSPeerInfoRef retired_peer = NULL;
- SecKeyRef key = SOSFullPeerInfoCopyDeviceKey(fpi, error);
- require_quiet(key, error_out);
-
- retired_peer = SOSPeerInfoCreateRetirementTicket(NULL, key, fpi->peer_info, error);
-
- require_quiet(retired_peer, error_out);
-
- peer_to_free = fpi->peer_info;
- fpi->peer_info = retired_peer;
- CFRetainSafe(fpi->peer_info);
-
-error_out:
- CFReleaseNull(key);
- CFReleaseNull(peer_to_free);
- return retired_peer;
-}
-
-
-