]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSFullPeerInfo.c
index 219c27081809f7fb6466537309a5e1cb97a01daf..ea3a6cc9a053745314f6a3bd24c47ad1b874eeb4 100644 (file)
@@ -84,7 +84,6 @@ struct __OpaqueSOSFullPeerInfo {
 CFGiblisWithHashFor(SOSFullPeerInfo);
 
 
-static CFStringRef sPublicKeyKey = CFSTR("PublicSigningKey");
 
 CFStringRef kSOSFullPeerInfoDescriptionKey = CFSTR("SOSFullPeerInfoDescription");
 CFStringRef kSOSFullPeerInfoSignatureKey = CFSTR("SOSFullPeerInfoSignature");
@@ -113,7 +112,7 @@ fail:
 
 bool SOSFullPeerInfoUpdateToThisPeer(SOSFullPeerInfoRef peer, SOSPeerInfoRef pi, CFErrorRef *error) {
     return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
-        return SOSPeerInfoSign(key, pi, error) ? pi: NULL;
+        return SOSPeerInfoSign(key, pi, error) ? CFRetainSafe(pi): NULL;
     });
 }
 
@@ -130,15 +129,14 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator,
     SOSFullPeerInfoRef result = NULL;
     SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
 
-    bool useIDS = whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture;
-
-    CFStringRef transportType = useIDS ? SOSTransportMessageTypeIDS : SOSTransportMessageTypeKVS;
-    CFBooleanRef preferIDS = useIDS ? kCFBooleanTrue : kCFBooleanFalse;
     CFStringRef IDSID = CFSTR("");
-
+    CFStringRef transportType =SOSTransportMessageTypeIDSV2;
+    CFBooleanRef preferIDS = kCFBooleanFalse;
+    CFBooleanRef preferIDSFragmentation = kCFBooleanTrue;
+    
     fpi->peer_info = SOSPeerInfoCreateWithTransportAndViews(allocator, gestalt, backupKey,
                                                             IDSID, transportType, preferIDS,
-                                                            initialViews,
+                                                            preferIDSFragmentation, initialViews,
                                                             signingKey, error);
     require_quiet(fpi->peer_info, exit);
 
@@ -152,6 +150,23 @@ exit:
     return result;
 }
 
+SOSFullPeerInfoRef SOSFullPeerInfoCopyFullPeerInfo(SOSFullPeerInfoRef toCopy) {
+    SOSFullPeerInfoRef retval = NULL;
+    SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, kCFAllocatorDefault);
+    SOSPeerInfoRef piToCopy = SOSFullPeerInfoGetPeerInfo(toCopy);
+    
+    require_quiet(piToCopy, errOut);
+    require_quiet(fpi, errOut);
+    fpi->peer_info = SOSPeerInfoCreateCopy(kCFAllocatorDefault, piToCopy, NULL);
+    require_quiet(fpi->peer_info, errOut);
+    fpi->key_ref = toCopy->key_ref;
+    CFTransferRetained(retval, fpi);
+
+errOut:
+    CFReleaseNull(fpi);
+    return retval;
+}
+
 bool SOSFullPeerInfoUpdateTransportType(SOSFullPeerInfoRef peer, CFStringRef transportType, CFErrorRef* error)
 {
     return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
@@ -171,6 +186,13 @@ bool SOSFullPeerInfoUpdateTransportPreference(SOSFullPeerInfoRef peer, CFBoolean
     });
 }
 
+bool SOSFullPeerInfoUpdateTransportFragmentationPreference(SOSFullPeerInfoRef peer, CFBooleanRef preference, CFErrorRef* error){
+    return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
+        return SOSPeerInfoSetIDSFragmentationPreference(kCFAllocatorDefault, peer, preference, key, error);
+    });
+}
+
+
 SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error) {
     SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
     
@@ -183,7 +205,8 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator,
         goto exit;
     }
 
-    pubKey = SOSPeerInfoCopyPubKey(peer);
+    pubKey = SOSPeerInfoCopyPubKey(peer, error);
+    require_quiet(pubKey, exit);
     
     fpi->key_ref = SecKeyCreatePersistentRefToMatchingPrivateKey(pubKey, error);
     
@@ -301,92 +324,90 @@ SOSViewResultCode SOSFullPeerInfoUpdateViews(SOSFullPeerInfoRef peer, SOSViewAct
 {
     __block SOSViewResultCode retval = kSOSCCGeneralViewError;
     
+    secnotice("viewChange", "%s view %@", SOSViewsXlateAction(action), viewname);
+    
     return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) {
         return SOSPeerInfoCopyWithViewsChange(kCFAllocatorDefault, peer, action, viewname, &retval, key, error);
     }) ? retval : kSOSCCGeneralViewError;
 }
 
+static CFMutableSetRef SOSFullPeerInfoCopyViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
+    CFSetRef enabledViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
+    CFMutableSetRef newViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
 
-static bool CFSetIsSubset(CFSetRef smaller, CFSetRef bigger) {
-    __block bool isSubset = true;
-    CFSetForEach(smaller, ^(const void *value) {
-        if (!CFSetContainsValue(bigger, value)) {
-            isSubset = false;
-        }
-    });
+    if (isSet(minimumViews)) {
+        CFSetUnion(newViews, minimumViews);
+    }
+    if (isSet(excludedViews)) {
+        CFSetSubtract(newViews, excludedViews);
+    }
 
-    return isSubset;
-}
+    if (CFEqualSafe(newViews, enabledViews)) {
+        CFReleaseNull(newViews);
+    }
 
-static void CFSetUnionSet(CFMutableSetRef target, CFSetRef source) {
-    CFSetForEach(source, ^(const void *value) {
-        CFSetAddValue(target, value);
-    });
+    CFReleaseNull(enabledViews);
+    return newViews;
 }
 
-static bool sosFullPeerInfoNeedsViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
-    CFSetRef currentViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
-    bool success = isSet(minimumViews) && (!isSet(currentViews) || !CFSetIsSubset(minimumViews, currentViews));
-    CFReleaseNull(currentViews);
-    return success;
+static bool SOSFullPeerInfoNeedsViewUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
+    CFSetRef updatedViews = SOSFullPeerInfoCopyViewUpdate(peer, minimumViews, excludedViews);
+    bool needsUpdate = (updatedViews != NULL);
+    CFReleaseNull(updatedViews);
+    return needsUpdate;
 }
 
-static bool sosFullPeerInfoRequiresUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
+static bool sosFullPeerInfoRequiresUpdate(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
     
     if(!SOSPeerInfoVersionIsCurrent(peer->peer_info)) return true;
     if(!SOSPeerInfoSerialNumberIsSet(peer->peer_info)) return true;
     if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sDeviceID)))return true;
     if(!(SOSPeerInfoV2DictionaryHasString(peer->peer_info, sTransportType))) return true;
     if(!(SOSPeerInfoV2DictionaryHasBoolean(peer->peer_info, sPreferIDS))) return true;
-    if(sosFullPeerInfoNeedsViewUpdate(peer, minimumViews)) return true;
+    if(!(SOSPeerInfoV2DictionaryHasBoolean(peer->peer_info, sPreferIDSFragmentation))) return true;
+    if(SOSFullPeerInfoNeedsViewUpdate(peer, minimumViews, excludedViews)) return true;
 
     return false;
 }
 
 // Returning false indicates we don't need to upgrade.
-bool SOSFullPeerInfoUpdateToCurrent(SOSFullPeerInfoRef peer, CFSetRef minimumViews) {
-    CFMutableSetRef newViews = NULL;
-    
-    if(!sosFullPeerInfoRequiresUpdate(peer, minimumViews)) return false;
+bool SOSFullPeerInfoUpdateToCurrent(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews) {
+    bool success = false;
 
-    CFSetRef currentViews = SOSPeerInfoCopyEnabledViews(peer->peer_info);
-    if (sosFullPeerInfoNeedsViewUpdate(peer, minimumViews)) {
-        newViews = isSet(currentViews) ? CFSetCreateMutableCopy(kCFAllocatorDefault, 0, currentViews) : CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
-        CFSetUnionSet(newViews, minimumViews);
-    }
-    
+    CFMutableSetRef newViews = NULL;
     CFErrorRef copyError = NULL;
     CFErrorRef createError = NULL;
-    SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peer, &copyError);
+    SecKeyRef device_key = NULL;
+
+    require_quiet(sosFullPeerInfoRequiresUpdate(peer, minimumViews, excludedViews), errOut);
+
+    newViews = SOSFullPeerInfoCopyViewUpdate(peer, minimumViews, excludedViews);
+
+    device_key = SOSFullPeerInfoCopyDeviceKey(peer, &copyError);
     require_action_quiet(device_key, errOut,
                          secnotice("upgrade", "SOSFullPeerInfoCopyDeviceKey failed: %@", copyError));
     
     SOSPeerInfoRef newPeer = SOSPeerInfoCreateCurrentCopy(kCFAllocatorDefault, peer->peer_info,
-                                                          NULL, NULL, NULL, newViews ? newViews : minimumViews,
+                                                          NULL, NULL, kCFBooleanFalse, kCFBooleanTrue, newViews,
                                                           device_key, &createError);
     require_action_quiet(newPeer, errOut,
                          secnotice("upgrade", "Peer info v2 create copy failed: %@", createError));
 
     CFTransferRetained(peer->peer_info, newPeer);
-    
-    CFReleaseNull(currentViews);
-    CFReleaseSafe(newViews);
-    CFReleaseNull(device_key);
-    return true;
-    
+
+    success = true;
+
 errOut:
-    CFReleaseNull(currentViews);
-    CFReleaseSafe(newViews);
+    CFReleaseNull(newViews);
     CFReleaseNull(copyError);
     CFReleaseNull(createError);
     CFReleaseNull(device_key);
-    return false;
+    return success;
 }
 
 SOSViewResultCode SOSFullPeerInfoViewStatus(SOSFullPeerInfoRef peer, CFStringRef viewname, CFErrorRef *error)
 {
     SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(peer);
-    secnotice("views", "have pi %s", (pi)? "true": "false");
     if(!pi) return kSOSCCGeneralViewError;
     return SOSPeerInfoViewStatus(pi, viewname, error);
 }
@@ -426,27 +447,35 @@ SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer) {
 
 // MARK: Private Key Retrieval and Existence
 
-static SecKeyRef SOSFullPeerInfoCopyPubKey(SOSFullPeerInfoRef fpi) {
+static SecKeyRef SOSFullPeerInfoCopyPubKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
     SecKeyRef retval = NULL;
     require_quiet(fpi, errOut);
     SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi);
     require_quiet(pi, errOut);
-    retval = SOSPeerInfoCopyPubKey(pi);
+    retval = SOSPeerInfoCopyPubKey(pi, error);
 
 errOut:
     return retval;
 }
 
 static SecKeyRef SOSFullPeerInfoCopyMatchingPrivateKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
-    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
-    SecKeyRef retval = SecKeyCopyMatchingPrivateKey(pub, error);
+    SecKeyRef retval = NULL;
+
+    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi, error);
+    require_quiet(pub, exit);
+    retval = SecKeyCopyMatchingPrivateKey(pub, error);
+exit:
     CFReleaseNull(pub);
     return retval;
 }
 
 static OSStatus SOSFullPeerInfoGetMatchingPrivateKeyStatus(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
-    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
-    OSStatus retval = SecKeyGetMatchingPrivateKeyStatus(pub, error);
+    OSStatus retval = errSecParam;
+    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi, error);
+    require_quiet(pub, exit);
+    retval = SecKeyGetMatchingPrivateKeyStatus(pub, error);
+
+exit:
     CFReleaseNull(pub);
     return retval;
 }
@@ -464,15 +493,24 @@ bool SOSFullPeerInfoPrivKeyExists(SOSFullPeerInfoRef peer) {
 }
 
 bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fpi, CFErrorRef* error) {
-    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi);
-    CFDictionaryRef privQuery = CreatePrivateKeyMatchingQuery(pub, false);
-    CFMutableDictionaryRef query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, privQuery);
+    bool result = false;
+    CFDictionaryRef privQuery = NULL;
+    CFMutableDictionaryRef query = NULL;
+
+    SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi, error);
+    require_quiet(pub, fail);
+
+    privQuery = CreatePrivateKeyMatchingQuery(pub, false);
+    query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, privQuery);
     CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanFalse);
-    SecItemDelete(query);
+
+    result = SecError(SecItemDelete(query), error, CFSTR("Deleting while purging"));
+
+fail:
     CFReleaseNull(privQuery);
     CFReleaseNull(query);
     CFReleaseNull(pub);
-    return true;
+    return result;
 }
 
 SecKeyRef  SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error) {