]> git.saurik.com Git - apple/security.git/commitdiff
Security-58286.251.4.tar.gz macos-10144 v58286.251.4
authorApple <opensource@apple.com>
Tue, 18 Jun 2019 00:54:59 +0000 (00:54 +0000)
committerApple <opensource@apple.com>
Tue, 18 Jun 2019 00:54:59 +0000 (00:54 +0000)
125 files changed:
OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist
OSX/authd/authd-Entitlements.plist
OSX/authd/authitems.c
OSX/authd/authutilities.c
OSX/authd/server.c
OSX/codesign_tests/SignatureEditing.sh [new file with mode: 0644]
OSX/config/security_framework_macos.xcconfig
OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp
OSX/libsecurity_codesigning/antlr2/src/CharBuffer.cpp
OSX/libsecurity_codesigning/lib/CodeSigner.cpp
OSX/libsecurity_codesigning/lib/CodeSigner.h
OSX/libsecurity_codesigning/lib/RequirementLexer.cpp
OSX/libsecurity_codesigning/lib/SecCode.cpp
OSX/libsecurity_codesigning/lib/SecCode.h
OSX/libsecurity_codesigning/lib/SecCodePriv.h
OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp
OSX/libsecurity_codesigning/lib/SecCodeSigner.h
OSX/libsecurity_codesigning/lib/StaticCode.cpp
OSX/libsecurity_codesigning/lib/StaticCode.h
OSX/libsecurity_codesigning/lib/antlrplugin.cpp
OSX/libsecurity_codesigning/lib/bundlediskrep.cpp
OSX/libsecurity_codesigning/lib/bundlediskrep.h
OSX/libsecurity_codesigning/lib/cdbuilder.cpp
OSX/libsecurity_codesigning/lib/cdbuilder.h
OSX/libsecurity_codesigning/lib/cskernel.cpp
OSX/libsecurity_codesigning/lib/csprocess.h
OSX/libsecurity_codesigning/lib/diskrep.h
OSX/libsecurity_codesigning/lib/machorep.cpp
OSX/libsecurity_codesigning/lib/machorep.h
OSX/libsecurity_codesigning/lib/piddiskrep.cpp
OSX/libsecurity_codesigning/lib/piddiskrep.h
OSX/libsecurity_codesigning/lib/sigblob.cpp
OSX/libsecurity_codesigning/lib/sigblob.h
OSX/libsecurity_codesigning/lib/signer.cpp
OSX/libsecurity_codesigning/lib/signer.h
OSX/libsecurity_codesigning/lib/signerutils.cpp
OSX/libsecurity_codesigning/lib/signerutils.h
OSX/libsecurity_codesigning/requirements.grammar
OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp
OSX/libsecurity_keychain/lib/Item.cpp
OSX/libsecurity_keychain/lib/KeyItem.cpp
OSX/libsecurity_keychain/lib/Keychains.cpp
OSX/libsecurity_keychain/lib/SecAccess.cpp
OSX/libsecurity_keychain/lib/SecItem.cpp
OSX/libsecurity_keychain/regressions/kc-45-change-password.c [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/keychain_regressions.h
OSX/libsecurity_keychain/xpc/main.c
OSX/libsecurity_smime/lib/cmssigdata.c
OSX/libsecurity_smime/regressions/cms-01-basic.c
OSX/libsecurity_smime/regressions/cms-01-basic.h
OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c
OSX/libsecurity_utilities/lib/errors.cpp
OSX/libsecurity_utilities/lib/errors.h
OSX/libsecurity_utilities/lib/machserver.cpp
OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h
OSX/sec/SOSCircle/SecureObjectSync/SOSDigestVector.c
OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c
OSX/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.m
OSX/sec/SOSCircle/SecureObjectSync/ViewList.list
OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c
OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h
OSX/sec/Security/SecAccessControl.c [deleted file]
OSX/sec/Security/SecAccessControl.m [new file with mode: 0644]
OSX/sec/Security/SecCTKKey.m
OSX/sec/Security/SecCTKKeyPriv.h
OSX/sec/Security/SecExports.exp-in
OSX/sec/Security/SecFrameworkStrings.h
OSX/sec/Security/SecItem.c
OSX/sec/Security/SecItemConstants.c
OSX/sec/Security/SecKey.c
OSX/sec/Security/SecKeyAdaptors.m
OSX/sec/securityd/OTATrustUtilities.m
OSX/sec/securityd/Regressions/secd-33-keychain-ctk.m
OSX/sec/securityd/SecPolicyServer.c
OSX/sec/securityd/SecRevocationNetworking.m
OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA2G1-Baltimore.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-Baltimore.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-DigiCert.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/BaltimoreCyberTrustRoot.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/DigiCertGlobalRootG3.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist
OSX/shared_regressions/si-20-sectrust-policies-data/caldav.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/generic_apple_server.cer
OSX/shared_regressions/si-20-sectrust-policies-data/itunes.cer [new file with mode: 0644]
OSX/shared_regressions/si-44-seckey-aks.m
OSX/shared_regressions/si-44-seckey-ies.m
OSX/shared_regressions/si-82-sectrust-ct.m
OSX/utilities/src/SecDb.c
OSX/utilities/src/iCloudKeychainTrace.c
Security.exp-in
Security.xcodeproj/project.pbxproj
SecurityTests/SecurityTests-Entitlements.plist
SecurityTool/keychain_export.m
SecurityTool/keychain_set_settings.c
SecurityTool/security.1
SecurityTool/security.c
cssm/cssmapple.h
keychain/CoreDataKeychain/SecCDKeychain.m
keychain/SecItem.h
keychain/SecItemPriv.h
keychain/SecKey.h
keychain/SecKeyPriv.h
keychain/ckks/CKKS.h
keychain/ckks/CKKS.m
keychain/ckks/CKKSIncomingQueueOperation.m
keychain/ckks/CKKSKeychainView.m
keychain/ckks/tests/CKKSSOSTests.m
keychain/ckks/tests/CKKSTests+API.m
keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m
libsecurity_smime/lib/cmssigdata.c
resources/English.lproj/OID.strings
resources/English.lproj/Trust.strings
sectask/SecTask.c
sectask/SecTaskPriv.h
securityd/securityd_service/securityd_service/main.c
securityd/src/SharedMemoryServer.cpp
securityd/src/agentquery.cpp
securityd/src/child.cpp
securityd/src/clientid.cpp
securityd/src/clientid.h
securityd/src/csproxy.cpp
securityd/src/kcdatabase.cpp
securityd/src/process.cpp
securityd/src/process.h
tests/secdmockaks/mockaks.m

index 01ffca584b4a48a17efa4c697b6287dac14aebc9..9b09881791fdde260a467f46c738dc87fe10f183 100644 (file)
@@ -10,6 +10,8 @@
        <true/>
        <key>com.apple.keystore.access-keychain-keys</key>
        <true/>
+       <key>com.apple.keystore.sik.access</key>
+       <true/>
        <key>com.apple.keystore.device</key>
        <true/>
        <key>restore-keychain</key>
index 7ef4f57c7622eb871b025d425d6ff731e3f5e22d..a1885cc8bb4711a7e52500a78d64f44cb1d50b34 100644 (file)
@@ -6,5 +6,7 @@
        <true/>
        <key>com.apple.keystore.console</key>
        <true/>
+       <key>com.apple.security.cs.disable-library-validation</key>
+       <true/>
 </dict>
 </plist>
index 463884e280684fcd1bf8111b7dae8c12970f4927..ea49287ad8ca864d148488dca7f5763fe5554833 100644 (file)
@@ -255,6 +255,10 @@ auth_item_create_with_xpc(xpc_object_t data)
         bool sensitive = xpc_dictionary_get_value(data, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
         if (sensitive) {
             size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(data, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
+            if (sensitiveLength > len) {
+                os_log_error(AUTHD_LOG, "Sensitive data len %zu is not valid", sensitiveLength);
+                goto done;
+            }
             item->bufLen = sensitiveLength;
             item->data.valueLength = sensitiveLength;
             item->data.value = calloc(1u, sensitiveLength);
index d769467b3abc4d0e5060567ec0dd48597ba8dc50..60b6b2fdfb54f8cfe390d8175eec93ef51b78be4 100644 (file)
@@ -7,6 +7,8 @@
 #include <AssertMacros.h>
 #include <assert.h>
 
+AUTHD_DEFINE_LOG
+
 xpc_object_t
 SerializeItemSet(const AuthorizationItemSet * itemSet)
 {
@@ -67,6 +69,10 @@ DeserializeItemSet(const xpc_object_t data)
             // <rdar://problem/13033889> authd is holding on to multiple copies of my password in the clear
             if (xpc_dictionary_get_value(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH) != NULL) {
                 size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
+                if (sensitiveLength > len) {
+                    os_log_error(AUTHD_LOG, "Sensitive data len %zu is not valid", sensitiveLength);
+                    goto done;
+                }
                 dataCopy = malloc(sensitiveLength);
                 require(dataCopy != NULL, done);
                 memcpy(dataCopy, valueData, sensitiveLength);
index 903c51c87fe5a0cdad717fa2a4707296d580c128..1c29b2ecb97d4c824b8d70682785a64464b3411c 100644 (file)
@@ -37,9 +37,6 @@ static CFMutableDictionaryRef gSessionMap = NULL;
 static CFMutableDictionaryRef gAuthTokenMap = NULL;
 static authdb_t gDatabase = NULL;
 
-static dispatch_queue_t power_queue;
-static bool gInDarkWake = false;
-static IOPMConnection gIOPMconn = NULL;
 static bool gXPCTransaction = false;
 
 static dispatch_queue_t
@@ -112,71 +109,15 @@ void server_cleanup()
     CFRelease(gSessionMap);
     CFRelease(gAuthTokenMap);
     
-    IOPMConnectionSetDispatchQueue(gIOPMconn, NULL);
-    IOPMConnectionRelease(gIOPMconn);
-    
     dispatch_queue_t queue = get_server_dispatch_queue();
     if (queue) {
         dispatch_release(queue);
     }
-    dispatch_release(power_queue);
-}
-
-static void _IOMPCallBack(void * param AUTH_UNUSED, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities)
-{
-    os_log_debug(AUTHD_LOG, "server: IOMP powerstates %i", capabilities);
-    if (capabilities & kIOPMSystemPowerStateCapabilityDisk)
-        os_log_debug(AUTHD_LOG, "server: disk");
-    if (capabilities & kIOPMSystemPowerStateCapabilityNetwork)
-        os_log_debug(AUTHD_LOG, "server: net");
-    if (capabilities & kIOPMSystemPowerStateCapabilityAudio)
-        os_log_debug(AUTHD_LOG, "server: audio");
-    if (capabilities & kIOPMSystemPowerStateCapabilityVideo)
-        os_log_debug(AUTHD_LOG, "server: video");
-    
-    /* if cpu and no display -> in DarkWake */
-    os_log_debug(AUTHD_LOG, "server: DarkWake check current=%i==%i", (capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)), kIOPMSystemPowerStateCapabilityCPU);
-    if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) {
-        os_log_debug(AUTHD_LOG, "server: enter DW");
-        gInDarkWake = true;
-    } else if (gInDarkWake) {
-        os_log_debug(AUTHD_LOG, "server: exit DW");
-        gInDarkWake = false;
-    }
-    
-    (void)IOPMConnectionAcknowledgeEvent(connection, token);
-    
-    return;
-}
-
-static void
-_setupDarkWake(void *__unused ctx)
-{
-    IOReturn ret;
-    
-    IOPMConnectionCreate(CFSTR("IOPowerWatcher"),
-                         kIOPMSystemPowerStateCapabilityDisk
-                         | kIOPMSystemPowerStateCapabilityNetwork
-                         | kIOPMSystemPowerStateCapabilityAudio
-                         | kIOPMSystemPowerStateCapabilityVideo,
-                         &gIOPMconn);
-
-    ret = IOPMConnectionSetNotification(gIOPMconn, NULL, _IOMPCallBack);
-    if (ret != kIOReturnSuccess)
-        return;
-    
-    IOPMConnectionSetDispatchQueue(gIOPMconn, power_queue);
-
-    IOPMScheduleUserActiveChangedNotification(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool active) {
-        if (active) {
-            gInDarkWake = false;
-        }
-    });
 }
 
 bool server_in_dark_wake()
 {
-    return gInDarkWake;
+    return IOPMIsADarkWake(IOPMConnectionGetSystemCapabilities());
 }
 
 authdb_t server_get_database()
@@ -256,10 +197,6 @@ OSStatus server_init(void)
     authdb_maintenance(dbconn);
     authdb_connection_release(&dbconn);
     
-    power_queue = dispatch_queue_create("com.apple.security.auth.power", DISPATCH_QUEUE_SERIAL);
-    require_action(power_queue != NULL, done, status = errAuthorizationInternal);
-    dispatch_async_f(power_queue, NULL, _setupDarkWake);
-
     _setupAuditSessionMonitor();
     _setupSignalHandlers();
     
diff --git a/OSX/codesign_tests/SignatureEditing.sh b/OSX/codesign_tests/SignatureEditing.sh
new file mode 100644 (file)
index 0000000..9aadfa9
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+v=${v:-:}
+
+fails=0
+t=$(mktemp -d /tmp/cs-edit-XXXXXX)
+
+runTest () {
+    test=$1
+    shift
+
+    echo "[BEGIN] ${test}"
+
+    ${v} echo "> $@"
+    "$@" > $t/outfile.txt 2>&1
+    res=$?
+    [ $res != 0 ] && res=1 #normalize
+
+    if expr "$test" : "fail"  > /dev/null; then
+        exp=1
+    else
+        exp=0
+    fi
+
+    ${v} cat $t/outfile.txt
+    if [ $res -eq $exp ]; then
+        echo "[PASS] ${test}"
+        echo
+        rm -f $t/outfile.txt
+    else
+        echo
+        cat $t/outfile.txt
+        echo
+        echo "[FAIL] ${test}"
+        echo
+        fails=$(($fails+1))
+    fi
+}
+
+codesign=${codesign:-codesign}
+
+editTest () {
+    name="$1"
+    shift
+    target="$1"
+    shift
+
+    rm -f $t/cms
+
+    runTest validate-$name $codesign -v -R="anchor apple" -v "$target"
+    runTest dump-cms-$name $codesign -d --dump-cms=$t/cms "$target"
+    runTest edit-nonsense-into-cms-$name $codesign -e "$target" --edit-cms /etc/hosts
+    runTest fail-nonsense-validation-$name $codesign -v -R="anchor apple" -v "$target"
+    runTest edit-original-into-cms-$name $codesign -e "$target" --edit-cms $t/cms
+    runTest success-cms-validation-$name $codesign -v -R="anchor apple" -v "$target"
+    runTest edit-cat-cms-into-cms-$name $codesign -e "$target" --edit-cms $t/cat.cms
+    runTest fail-cat-cms-validation-$name $codesign -v -R="anchor apple" -v "$target"
+    runTest edit-original-again-into-cms-$name $codesign -e "$target" --edit-cms $t/cms
+    runTest success-cms-validation-again-$name $codesign -v -R="anchor apple" -v "$target"
+}
+
+runTest dump-cat-cms $codesign -d --dump-cms=$t/cat.cms /bin/cat
+
+runTest prepare-ls cp -R /bin/ls $t/ls
+editTest ls $t/ls
+runTest prepare-TextEdit cp -R /Applications/TextEdit.app $t/TextEdit.app
+editTest TextEdit $t/TextEdit.app
+
+runTest prepare-codeless cp -R /var/db/gke.bundle $t/gke.bundle
+editTest codeless $t/gke.bundle
+
+runTest codesign-remove-signature $codesign --remove $t/ls
+runTest codesign-omit-adhoc $codesign -s - -f --omit-adhoc-flag $t/ls
+runTest adhoc-omitted sh -c "$codesign -d -v $t/ls 2>&1| grep -F 'flags=0x0(none)'"
+
+# cleanup
+
+if [ $fails != 0 ] ; then
+    echo "$fails signature edit tests failed"
+    exit 1
+else
+    echo "all signature edit tests passed"
+    rm -rf $t
+fi
+
+exit 0
index 1fb5b36f6a2a45dea48df318eeacb75439d37645..09b9eb843da6aafac011d3cfb45f4c86388bc2e2 100644 (file)
@@ -17,7 +17,8 @@ INFOPLIST_FILE = OSX/lib/Info-Security.plist
 
 INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks
 
-OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation -Wl,-no_inits
+ASAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits
+OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation -Wl,-no_inits $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER))
 
 SECTORDER_FLAGS = -order_file_statistics
 APPLY_RULES_IN_COPY_FILES = NO
index be200db38dcb20992a5935a1252693c64340672a..a7e46bcd4b384e6308cef5dc9d839909ea125cf1 100644 (file)
@@ -40,11 +40,26 @@ request(xpc_connection_t peer, xpc_object_t event)
        if (pid <= 0)
                return;
        
+       size_t audit_size;
+       audit_token_t const *audit =
+               (audit_token_t const *)xpc_dictionary_get_data(event, "audit", &audit_size);
+       
+       if (audit != NULL && audit_size != sizeof(audit_token_t)) {
+               Syslog::error("audit token has unexpected size %zu", audit_size);
+               return;
+       }
+       
        xpc_object_t reply = xpc_dictionary_create_reply(event);
        if (reply == NULL)
                return;
        
-       CFTemp<CFDictionaryRef> attributes("{%O=%d}", kSecGuestAttributePid, pid);
+       CFTemp<CFMutableDictionaryRef> attributes("{%O=%d}", kSecGuestAttributePid, pid);
+    
+       if (audit != NULL) {
+               CFRef<CFDataRef> auditData = makeCFData(audit, audit_size);
+               CFDictionaryAddValue(attributes.get(), kSecGuestAttributeAudit,
+                                                        auditData);
+       }
        CFRef<SecCodeRef> code;
        if ((rc = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref())) == noErr) {
                
index c40495e310d3cc062866e2ec05a4250dbca131f0..b58bd35456d2755865e0d2afd40838781609be4a 100644 (file)
@@ -40,7 +40,15 @@ CharBuffer::CharBuffer(ANTLR_USE_NAMESPACE(std)istream& input_)
 int CharBuffer::getChar()
 {
 //     try {
-               return input.get();
+    int i = input.get();
+    
+    if (i == -1) {
+        // pass through EOF
+        return -1;
+    }
+    
+    // prevent negative-valued characters through sign extension of high-bit characters
+    return static_cast<int>(static_cast<unsigned char>(i));
 //     }
 //     catch (ANTLR_USE_NAMESPACE(std)ios_base::failure& e) {
 //             throw CharStreamIOException(e);
index 84383ca6214074f85b5e57554aeeb1722228109e..bc11737f28fc70528b10f54b4db77f34cc580abf 100644 (file)
@@ -170,8 +170,9 @@ std::string SecCodeSigner::getTeamIDFromSigner(CFArrayRef certs)
 //
 bool SecCodeSigner::valid() const
 {
-       if (mOpFlags & kSecCSRemoveSignature)
+       if (mOpFlags & (kSecCSRemoveSignature | kSecCSEditSignature)) {
                return true;
+       }
        return mSigner;
 }
 
@@ -188,6 +189,9 @@ void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags)
        if ((flags | mOpFlags) & kSecCSRemoveSignature) {
                secinfo("signer", "%p will remove signature from %p", this, code);
                operation.remove(flags);
+       } else if ((flags | mOpFlags) & kSecCSEditSignature) {
+               secinfo("signer", "%p will edit signature of %p", this, code);
+               operation.edit(flags);
        } else {
                if (!valid())
                        MacOSError::throwMe(errSecCSInvalidObjectRef);
@@ -229,6 +233,29 @@ void SecCodeSigner::returnDetachedSignature(BlobCore *blob, Signer &signer)
 SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters)
        : CFDictionary(parameters, errSecCSBadDictionaryFormat)
 {
+       CFNumberRef editCpuType = get<CFNumberRef>(kSecCodeSignerEditCpuType);
+       CFNumberRef editCpuSubtype = get<CFNumberRef>(kSecCodeSignerEditCpuSubtype);
+       if (editCpuType != NULL && editCpuSubtype != NULL) {
+               state.mEditArch = Architecture(cfNumber<uint32_t>(editCpuType),
+                                                                          cfNumber<uint32_t>(editCpuSubtype));
+       }
+       
+       state.mEditCMS = get<CFDataRef>(kSecCodeSignerEditCMS);
+       
+       state.mDryRun = getBool(kSecCodeSignerDryRun);
+       
+       state.mSDKRoot = get<CFURLRef>(kSecCodeSignerSDKRoot);
+       
+       state.mPreserveAFSC = getBool(kSecCodeSignerPreserveAFSC);
+       
+       if (state.mOpFlags & kSecCSEditSignature) {
+               return;
+               /* Everything below this point is irrelevant for
+                * Signature Editing, which does not create any
+                * parts of the signature, only replaces them.
+                */
+       }
+
        // the signer may be an identity or null
        state.mSigner = SecIdentityRef(get<CFTypeRef>(kSecCodeSignerIdentity));
        if (state.mSigner)
@@ -305,15 +332,11 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters)
                        MacOSError::throwMe(errSecCSInvalidObjectRef);
        }
        
-       state.mDryRun = getBool(kSecCodeSignerDryRun);
-
        state.mResourceRules = get<CFDictionaryRef>(kSecCodeSignerResourceRules);
        
        state.mApplicationData = get<CFDataRef>(kSecCodeSignerApplicationData);
        state.mEntitlementData = get<CFDataRef>(kSecCodeSignerEntitlements);
        
-       state.mSDKRoot = get<CFURLRef>(kSecCodeSignerSDKRoot);
-    
        if (CFBooleanRef timestampRequest = get<CFBooleanRef>(kSecCodeSignerRequireTimestamp)) {
                state.mWantTimeStamp = timestampRequest == kCFBooleanTrue;
        } else {        // pick default
@@ -336,7 +359,10 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters)
                }
                state.mRuntimeVersionOverride = parseRuntimeVersion(runtime);
        }
-       state.mPreserveAFSC = getBool(kSecCodeSignerPreserveAFSC);
+       
+       // Don't add the adhoc flag, even if no signer identity was specified.
+       // Useful for editing in the CMS at a later point.
+       state.mOmitAdhocFlag = getBool(kSecCodeSignerOmitAdhocFlag);
 }
 
 
index d8888f09f791efe509f7b7d2db7b890dd06a0ade..099d18c7e33edf1d0edd30ca982c97d8ad4b4091 100644 (file)
@@ -95,7 +95,12 @@ public:
        LimitedAsync *mLimitedAsync;    // limited async workers for verification
        uint32_t mRuntimeVersionOverride;       // runtime Version Override
        bool mPreserveAFSC;             // preserve AFSC compression
+       bool mOmitAdhocFlag;                    // don't add adhoc flag, even without signer identity
 
+       // Signature Editing
+       Architecture mEditArch;                 // architecture to edit (defaults to all if empty)
+       CFRef<CFDataRef> mEditCMS;              // CMS to replace in the signature
+       
 };
 
 
index 83296a4ae7b312860e525e273e9dda9a3bdf6597..646bfaae8452d9a65da72cbe0ea19c9449d5d23d 100644 (file)
@@ -703,156 +703,25 @@ void RequirementLexer::mSTRING(bool _createToken) {
        text.erase(_saveIndex);
        { // ( ... )*
        for (;;) {
-               switch ( LA(1)) {
-               case 0x5c /* '\\' */ :
-               {
+               if ((LA(1) == 0x5c /* '\\' */ )) {
                        {
                        _saveIndex = text.length();
                        match('\\' /* charlit */ );
                        text.erase(_saveIndex);
                        match('\"' /* charlit */ );
                        }
-                       break;
                }
-               case 0x0 /* '\0' */ :
-               case 0x1 /* '\1' */ :
-               case 0x2 /* '\2' */ :
-               case 0x3 /* '\3' */ :
-               case 0x4 /* '\4' */ :
-               case 0x5 /* '\5' */ :
-               case 0x6 /* '\6' */ :
-               case 0x7 /* '\7' */ :
-               case 0x8 /* '\10' */ :
-               case 0x9 /* '\t' */ :
-               case 0xa /* '\n' */ :
-               case 0xb /* '\13' */ :
-               case 0xc /* '\14' */ :
-               case 0xd /* '\r' */ :
-               case 0xe /* '\16' */ :
-               case 0xf /* '\17' */ :
-               case 0x10 /* '\20' */ :
-               case 0x11 /* '\21' */ :
-               case 0x12 /* '\22' */ :
-               case 0x13 /* '\23' */ :
-               case 0x14 /* '\24' */ :
-               case 0x15 /* '\25' */ :
-               case 0x16 /* '\26' */ :
-               case 0x17 /* '\27' */ :
-               case 0x18 /* '\30' */ :
-               case 0x19 /* '\31' */ :
-               case 0x1a /* '\32' */ :
-               case 0x1b /* '\33' */ :
-               case 0x1c /* '\34' */ :
-               case 0x1d /* '\35' */ :
-               case 0x1e /* '\36' */ :
-               case 0x1f /* '\37' */ :
-               case 0x20 /* ' ' */ :
-               case 0x21 /* '!' */ :
-               case 0x23 /* '#' */ :
-               case 0x24 /* '$' */ :
-               case 0x25 /* '%' */ :
-               case 0x26 /* '&' */ :
-               case 0x27 /* '\'' */ :
-               case 0x28 /* '(' */ :
-               case 0x29 /* ')' */ :
-               case 0x2a /* '*' */ :
-               case 0x2b /* '+' */ :
-               case 0x2c /* ',' */ :
-               case 0x2d /* '-' */ :
-               case 0x2e /* '.' */ :
-               case 0x2f /* '/' */ :
-               case 0x30 /* '0' */ :
-               case 0x31 /* '1' */ :
-               case 0x32 /* '2' */ :
-               case 0x33 /* '3' */ :
-               case 0x34 /* '4' */ :
-               case 0x35 /* '5' */ :
-               case 0x36 /* '6' */ :
-               case 0x37 /* '7' */ :
-               case 0x38 /* '8' */ :
-               case 0x39 /* '9' */ :
-               case 0x3a /* ':' */ :
-               case 0x3b /* ';' */ :
-               case 0x3c /* '<' */ :
-               case 0x3d /* '=' */ :
-               case 0x3e /* '>' */ :
-               case 0x3f /* '?' */ :
-               case 0x40 /* '@' */ :
-               case 0x41 /* 'A' */ :
-               case 0x42 /* 'B' */ :
-               case 0x43 /* 'C' */ :
-               case 0x44 /* 'D' */ :
-               case 0x45 /* 'E' */ :
-               case 0x46 /* 'F' */ :
-               case 0x47 /* 'G' */ :
-               case 0x48 /* 'H' */ :
-               case 0x49 /* 'I' */ :
-               case 0x4a /* 'J' */ :
-               case 0x4b /* 'K' */ :
-               case 0x4c /* 'L' */ :
-               case 0x4d /* 'M' */ :
-               case 0x4e /* 'N' */ :
-               case 0x4f /* 'O' */ :
-               case 0x50 /* 'P' */ :
-               case 0x51 /* 'Q' */ :
-               case 0x52 /* 'R' */ :
-               case 0x53 /* 'S' */ :
-               case 0x54 /* 'T' */ :
-               case 0x55 /* 'U' */ :
-               case 0x56 /* 'V' */ :
-               case 0x57 /* 'W' */ :
-               case 0x58 /* 'X' */ :
-               case 0x59 /* 'Y' */ :
-               case 0x5a /* 'Z' */ :
-               case 0x5b /* '[' */ :
-               case 0x5d /* ']' */ :
-               case 0x5e /* '^' */ :
-               case 0x5f /* '_' */ :
-               case 0x60 /* '`' */ :
-               case 0x61 /* 'a' */ :
-               case 0x62 /* 'b' */ :
-               case 0x63 /* 'c' */ :
-               case 0x64 /* 'd' */ :
-               case 0x65 /* 'e' */ :
-               case 0x66 /* 'f' */ :
-               case 0x67 /* 'g' */ :
-               case 0x68 /* 'h' */ :
-               case 0x69 /* 'i' */ :
-               case 0x6a /* 'j' */ :
-               case 0x6b /* 'k' */ :
-               case 0x6c /* 'l' */ :
-               case 0x6d /* 'm' */ :
-               case 0x6e /* 'n' */ :
-               case 0x6f /* 'o' */ :
-               case 0x70 /* 'p' */ :
-               case 0x71 /* 'q' */ :
-               case 0x72 /* 'r' */ :
-               case 0x73 /* 's' */ :
-               case 0x74 /* 't' */ :
-               case 0x75 /* 'u' */ :
-               case 0x76 /* 'v' */ :
-               case 0x77 /* 'w' */ :
-               case 0x78 /* 'x' */ :
-               case 0x79 /* 'y' */ :
-               case 0x7a /* 'z' */ :
-               case 0x7b /* '{' */ :
-               case 0x7c /* '|' */ :
-               case 0x7d /* '}' */ :
-               case 0x7e /* '~' */ :
-               case 0x7f:
-               {
+               else if ((_tokenSet_2.member(LA(1)))) {
                        {
                        {
                        match(_tokenSet_2);
                        }
                        }
-                       break;
                }
-               default:
-               {
+               else {
                        goto _loop66;
                }
-               }
+               
        }
        _loop66:;
        } // ( ... )*
@@ -1241,30 +1110,30 @@ void RequirementLexer::mCPP_COMMENT(bool _createToken) {
 }
 
 
-const unsigned long RequirementLexer::_tokenSet_0_data_[] = { 0UL, 0UL, 134217726UL, 134217726UL, 0UL, 0UL, 0UL, 0UL };
-const antlr::BitSet RequirementLexer::_tokenSet_0(_tokenSet_0_data_,8);
-const unsigned long RequirementLexer::_tokenSet_1_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL };
+const unsigned long RequirementLexer::_tokenSet_0_data_[] = { 0UL, 0UL, 134217726UL, 134217726UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
+const antlr::BitSet RequirementLexer::_tokenSet_0(_tokenSet_0_data_,10);
+const unsigned long RequirementLexer::_tokenSet_1_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
 // 0 1 2 3 4 5 6 7 8 9 
-const antlr::BitSet RequirementLexer::_tokenSet_1(_tokenSet_1_data_,8);
-const unsigned long RequirementLexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4026531839UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL };
+const antlr::BitSet RequirementLexer::_tokenSet_1(_tokenSet_1_data_,10);
+const unsigned long RequirementLexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4026531839UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
 // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 
 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 
 // 0x1f   ! # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : 
-const antlr::BitSet RequirementLexer::_tokenSet_2(_tokenSet_2_data_,8);
-const unsigned long RequirementLexer::_tokenSet_3_data_[] = { 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL };
+const antlr::BitSet RequirementLexer::_tokenSet_2(_tokenSet_2_data_,16);
+const unsigned long RequirementLexer::_tokenSet_3_data_[] = { 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
 // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xd 0xe 0xf 0x10 0x11 
 // 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 
 //   ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : 
-const antlr::BitSet RequirementLexer::_tokenSet_3(_tokenSet_3_data_,8);
-const unsigned long RequirementLexer::_tokenSet_4_data_[] = { 4294967295UL, 4294934527UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL };
+const antlr::BitSet RequirementLexer::_tokenSet_3(_tokenSet_3_data_,16);
+const unsigned long RequirementLexer::_tokenSet_4_data_[] = { 4294967295UL, 4294934527UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
 // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 
 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 
 // 0x1f   ! \" # $ % & \' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 : 
-const antlr::BitSet RequirementLexer::_tokenSet_4(_tokenSet_4_data_,8);
-const unsigned long RequirementLexer::_tokenSet_5_data_[] = { 4294967295UL, 4294966271UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL };
+const antlr::BitSet RequirementLexer::_tokenSet_4(_tokenSet_4_data_,16);
+const unsigned long RequirementLexer::_tokenSet_5_data_[] = { 4294967295UL, 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL };
 // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 
 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 
 // 0x1f   ! \" # $ % & \' ( ) + , - . / 0 1 2 3 4 5 6 7 8 9 : 
-const antlr::BitSet RequirementLexer::_tokenSet_5(_tokenSet_5_data_,8);
+const antlr::BitSet RequirementLexer::_tokenSet_5(_tokenSet_5_data_,16);
 
 ANTLR_END_NAMESPACE
index f3269c91f3b2fab196258958d089d41815329f2f..dac2376cd6d282fd170b8511b65856b88780b3da 100644 (file)
@@ -179,7 +179,8 @@ OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef,
 
 
 //
-// Shorthand for getting the SecCodeRef for a UNIX process
+// Deprecated since 10.6, DO NOT USE. This can be raced.
+// Use SecCodeCreateWithAuditToken instead.
 //
 OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef)
 {
@@ -193,6 +194,25 @@ OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRe
 
        END_CSAPI
 }
+
+//
+// Shorthand for getting the SecCodeRef for a UNIX process
+//
+OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit,
+                                                                        SecCSFlags flags, SecCodeRef *processRef)
+{
+       BEGIN_CSAPI
+       
+       checkFlags(flags);
+       CFRef<CFDataRef> auditData = makeCFData(audit, sizeof(audit_token_t));
+       if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%O}", kSecGuestAttributeAudit, auditData.get()))) {
+               CodeSigning::Required(processRef) = guest->handle(false);
+       } else {
+               return errSecCSNoSuchCode;
+       }
+       
+       END_CSAPI
+}
 #endif // TARGET_OS_OSX
 
 
@@ -258,14 +278,16 @@ const CFStringRef kSecCodeInfoTimestamp =         CFSTR("signing-timestamp");
 const CFStringRef kSecCodeInfoTrust =                  CFSTR("trust");
 const CFStringRef kSecCodeInfoUnique =                 CFSTR("unique");
 const CFStringRef kSecCodeInfoCdHashes =        CFSTR("cdhashes");
+const CFStringRef kSecCodeInfoCdHashesFull =   CFSTR("cdhashes-full");
 const CFStringRef kSecCodeInfoRuntimeVersion =         CFSTR("runtime-version");
 
-
 const CFStringRef kSecCodeInfoCodeDirectory =  CFSTR("CodeDirectory");
 const CFStringRef kSecCodeInfoCodeOffset =             CFSTR("CodeOffset");
 const CFStringRef kSecCodeInfoDiskRepInfo =     CFSTR("DiskRepInfo");
 const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory");
 const CFStringRef kSecCodeInfoNotarizationDate = CFSTR("NotarizationDate");
+const CFStringRef kSecCodeInfoCMSDigestHashType = CFSTR("CMSDigestHashType");
+const CFStringRef kSecCodeInfoCMSDigest =        CFSTR("CMSDigest");
 
 /* DiskInfoRepInfo types */
 const CFStringRef kSecCodeInfoDiskRepVersionPlatform =         CFSTR("VersionPlatform");
@@ -285,7 +307,8 @@ OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flag
                | kSecCSRequirementInformation
                | kSecCSDynamicInformation
                | kSecCSContentInformation
-        | kSecCSSkipResourceDirectory);
+        | kSecCSSkipResourceDirectory
+               | kSecCSCalculateCMSDigest);
 
        SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
        CFRef<CFDictionaryRef> info = code->signingInformation(flags);
index b1a6afbc1b5f498cae1dfc7826fb846a7e27871b..5ccfb17051aa528ef504c20df6117286280356f4 100644 (file)
@@ -427,7 +427,8 @@ CF_ENUM(uint32_t) {
        kSecCSRequirementInformation = 1 << 2,
        kSecCSDynamicInformation = 1 << 3,
        kSecCSContentInformation = 1 << 4,
-    kSecCSSkipResourceDirectory = 1 << 5
+    kSecCSSkipResourceDirectory = 1 << 5,
+    kSecCSCalculateCMSDigest = 1 << 6,
 };
                                                                                                        /* flag required to get this value */
 extern const CFStringRef kSecCodeInfoCertificates;     /* Signing */
index 4073c23f488645d631de409f201b7a77d643ba92..3bce444bde38eed5e469422445931375bfcffff4 100644 (file)
@@ -38,13 +38,15 @@ extern "C" {
 
 /*
  *     Private constants for SecCodeCopySigningInformation.
- *     These are returned with the 
  */
+extern const CFStringRef kSecCodeInfoCdHashesFull;          /* Internal */
 extern const CFStringRef kSecCodeInfoCodeDirectory;                    /* Internal */
 extern const CFStringRef kSecCodeInfoCodeOffset;                       /* Internal */
 extern const CFStringRef kSecCodeInfoDiskRepInfo;           /* Internal */
 extern const CFStringRef kSecCodeInfoResourceDirectory;                /* Internal */
 extern const CFStringRef kSecCodeInfoNotarizationDate;      /* Internal */
+extern const CFStringRef kSecCodeInfoCMSDigestHashType;     /* Internal */
+extern const CFStringRef kSecCodeInfoCMSDigest;             /* Internal */
 
 extern const CFStringRef kSecCodeInfoDiskRepVersionPlatform;     /* Number */
 extern const CFStringRef kSecCodeInfoDiskRepVersionMin;          /* Number */
@@ -129,21 +131,23 @@ OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef code, SecRequirementTyp
 
 #if TARGET_OS_OSX
 /*!
-       @function SecCodeCreateWithPID
+       @function SecCodeCreateWithAuditToken
        Asks the kernel to return a SecCode object for a process identified
-       by a UNIX process id (pid). This is a shorthand for asking SecGetRootCode()
-       for a guest whose "pid" attribute has the given pid value.
+       by a UNIX audit token. This is a shorthand for asking SecGetRootCode()
+       for a guest whose "audit" attribute has the given audit token.
        
-       This is a deprecated convenience function.
-       Call SecCodeCopyGuestWithAttributes instead.
-       
-       @param pid A process id for an existing UNIX process on the system.
+       @param audit A process audit token for an existing UNIX process on the system.
        @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior.
        @param process On successful return, a SecCode object reference identifying
        the requesteed process.
        @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in
        CSCommon.h or certain other Security framework headers.
 */
+OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit,
+                                     SecCSFlags flags, SecCodeRef *process)
+    AVAILABLE_MAC_OS_X_VERSION_10_14_4_AND_LATER;
+    
+/* Deprecated and unsafe, DO NOT USE. */
 OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *process)
        AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
 #endif
index a7e31f657312053d8505c0114664d00b3426c6dc..7e09f760496128dd1d5ee2e0063a17d7da80e700 100644 (file)
@@ -60,7 +60,13 @@ const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata");
 const CFStringRef kSecCodeSignerTeamIdentifier =       CFSTR("teamidentifier");
 const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier");
 const CFStringRef kSecCodeSignerRuntimeVersion = CFSTR("runtime-version");
-const CFStringRef kSecCodeSignerPreserveAFSC = CFSTR("preserve-afsc");
+const CFStringRef kSecCodeSignerPreserveAFSC =         CFSTR("preserve-afsc");
+const CFStringRef kSecCodeSignerOmitAdhocFlag =        CFSTR("omit-adhoc-flag");
+
+// Keys for signature editing
+const CFStringRef kSecCodeSignerEditCpuType =  CFSTR("edit-cpu-type");
+const CFStringRef kSecCodeSignerEditCpuSubtype = CFSTR("edit-cpu-subtype");
+const CFStringRef kSecCodeSignerEditCMS =              CFSTR("edit-cms");
 
 
 
@@ -84,7 +90,8 @@ OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags,
        BEGIN_CSAPI
                
        checkFlags(flags,
-                 kSecCSRemoveSignature
+                 kSecCSEditSignature
+               | kSecCSRemoveSignature
                | kSecCSSignPreserveSignature
                | kSecCSSignNestedCode
                | kSecCSSignOpaque
index 2da5670f1d817cd6073d372a92e06a38e00a7cd8..eba1183066b0226d3e772f4de680ccd918d79891 100644 (file)
@@ -165,6 +165,10 @@ extern const CFStringRef kSecCodeSignerTeamIdentifier;
 extern const CFStringRef kSecCodeSignerPlatformIdentifier;
 extern const CFStringRef kSecCodeSignerRuntimeVersion;
 extern const CFStringRef kSecCodeSignerPreserveAFSC;
+extern const CFStringRef kSecCodeSignerOmitAdhocFlag;
+extern const CFStringRef kSecCodeSignerEditCpuType;
+extern const CFStringRef kSecCodeSignerEditCpuSubtype;
+extern const CFStringRef kSecCodeSignerEditCMS;
 
 enum {
     kSecCodeSignerPreserveIdentifier = 1 << 0,         // preserve signing identifier
@@ -189,7 +193,9 @@ enum {
                useful defaults, and will need to be set before signing is attempted.
        @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior.
                The kSecCSRemoveSignature flag requests that any existing signature be stripped
-               from the target code instead of signing.
+               from the target code instead of signing. The kSecCSEditSignature flag
+        requests editing of existing signatures, which only works with a very
+        limited set of options.
        @param staticCode On successful return, a SecStaticCode object reference representing
        the file system origin of the given SecCode. On error, unchanged.
        @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in
@@ -206,6 +212,7 @@ enum {
        kSecCSSignStrictPreflight = 1 << 7, // fail signing operation if signature would fail strict validation
        kSecCSSignGeneratePEH = 1 << 8,         // generate pre-encryption hashes
     kSecCSSignGenerateEntitlementDER = 1 << 9, // generate entitlement DER
+    kSecCSEditSignature = 1 << 10,      // edit existing signature
 };
 
 
index 74038fcc9a25c958338f843957c975d7f0832e8f..5b8b37aef6f3acaf380b4913e303899bf6236972 100644 (file)
@@ -548,6 +548,26 @@ CFArrayRef SecStaticCode::cdHashes()
        return mCDHashes;
 }
 
+//
+// Get a dictionary of untruncated cdhashes for all digest types in this signature.
+//
+CFDictionaryRef SecStaticCode::cdHashesFull()
+{
+       if (!mCDHashFullDict) {
+               CFRef<CFMutableDictionaryRef> cdDict = makeCFMutableDictionary();
+               for (auto const &it : mCodeDirectories) {
+                       CodeDirectory::HashAlgorithm alg = it.first;
+                       const CodeDirectory *cd = (const CodeDirectory *)CFDataGetBytePtr(it.second);
+                       CFRef<CFDataRef> hash = cd->cdhash(false);
+                       if (hash) {
+                               CFDictionaryAddValue(cdDict, CFTempNumber(alg), hash);
+                       }
+               }
+               mCDHashFullDict = cdDict.get();
+       }
+       return mCDHashFullDict;
+}
+
 
 //
 // Return the CMS signature blob; NULL if none found.
@@ -1986,6 +2006,7 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags)
        CFDictionaryAddValue(dict, kSecCodeInfoSource, CFTempString(this->signatureSource()));
        CFDictionaryAddValue(dict, kSecCodeInfoUnique, this->cdHash());
        CFDictionaryAddValue(dict, kSecCodeInfoCdHashes, this->cdHashes());
+       CFDictionaryAddValue(dict, kSecCodeInfoCdHashesFull, this->cdHashesFull());
        const CodeDirectory* cd = this->codeDirectory(false);
        CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithm, CFTempNumber(cd->hashType));
        CFRef<CFArrayRef> digests = makeCFArrayFrom(^CFTypeRef(CodeDirectory::HashAlgorithm type) { return CFTempNumber(type); }, hashAlgorithms());
@@ -2087,6 +2108,16 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags)
                }
        }
 
+       if (flags & kSecCSCalculateCMSDigest) {
+               try {
+                       CFDictionaryAddValue(dict, kSecCodeInfoCMSDigestHashType, CFTempNumber(cmsDigestHashType()));
+                       
+                       CFRef<CFDataRef> cmsDigest = createCmsDigest();
+                       if (cmsDigest) {
+                               CFDictionaryAddValue(dict, kSecCodeInfoCMSDigest, cmsDigest.get());
+                       }
+               } catch (...) { }
+       }
 
        //
        // kSecCSContentInformation adds more information about the physical layout
@@ -2297,5 +2328,30 @@ bool SecStaticCode::isAppleDeveloperCert(CFArrayRef certs)
        return req->requirement()->validates(ctx);
 }
 
+CFDataRef SecStaticCode::createCmsDigest()
+{
+       /*
+        * The CMS digest is a hash of the primary (first, most compatible) code directory,
+        * but its hash algorithm is fixed and not related to the code directory's
+        * hash algorithm.
+        */
+       
+       auto it = codeDirectories()->begin();
+       
+       if (it == codeDirectories()->end()) {
+               return NULL;
+       }
+
+       CodeDirectory const * const cd = reinterpret_cast<CodeDirectory const*>(CFDataGetBytePtr(it->second));
+       
+       RefPointer<DynamicHash> hash = cd->hashFor(mCMSDigestHashType);
+       CFMutableDataRef data = CFDataCreateMutable(NULL, hash->digestLength());
+       CFDataSetLength(data, hash->digestLength());
+       hash->update(cd, cd->length());
+       hash->finish(CFDataGetMutableBytePtr(data));
+       
+       return data;
+}
+       
 } // end namespace CodeSigning
 } // end namespace Security
index 2ca6d7da2a23f7d30d059c922706072b5cc99529..567268243d6d3ac10e16c8c0cc492bb4a67f4286 100644 (file)
@@ -125,6 +125,7 @@ public:
        CodeDirectory::HashAlgorithms hashAlgorithms() const { return mHashAlgorithms; }
        CFDataRef cdHash();
        CFArrayRef cdHashes();
+       CFDictionaryRef cdHashesFull();
        CFDataRef signature();
        CFAbsoluteTime signingTime();
        CFAbsoluteTime signingTimestamp();
@@ -205,6 +206,8 @@ public:
 
        void handleOtherArchitectures(void (^handle)(SecStaticCode* other));
 
+       uint8_t cmsDigestHashType() const { return mCMSDigestHashType; };
+       CFDataRef createCmsDigest();
 public:
        void staticValidate(SecCSFlags flags, const SecRequirement *req);
        void staticValidateCore(SecCSFlags flags, const SecRequirement *req);
@@ -233,6 +236,8 @@ private:
        dispatch_once_t mCheckfix30814861builder1_once;
        
 private:
+       static const uint8_t mCMSDigestHashType = kSecCodeSignatureHashSHA256;
+                                                                               // hash of CMS digest (kSecCodeSignatureHash* constant)
        RefPointer<DiskRep> mRep;                       // on-disk representation
        mutable CodeDirectoryMap mCodeDirectories; // available CodeDirectory blobs by digest type
        mutable CFRef<CFDataRef> mBaseDir;      // the primary CodeDirectory blob (whether it's chosen or not)
@@ -284,7 +289,8 @@ private:
        const Requirement *mDesignatedReq;      // cached designated req if we made one up
        CFRef<CFDataRef> mCDHash;                       // hash of chosen CodeDirectory
        CFRef<CFArrayRef> mCDHashes;            // hashes of all CodeDirectories (in digest type code order)
-       
+       CFRef<CFDictionaryRef> mCDHashFullDict; // untruncated hashes of CodeDirectories (as dictionary)
+
        bool mGotResourceBase;                          // asked mRep for resourceBasePath
        CFRef<CFURLRef> mResourceBase;          // URL form of resource base directory
 
index 0e4dee56b57c36a60e81733cdd26ada6d4ccf54d..306207aae49c355b452df510cd5da85c1f3ad25e 100644 (file)
@@ -49,7 +49,7 @@ private:
 class StringInputStream : public antlr::InputBuffer {
 public:
        StringInputStream(const string &s) : mInput(s), mPos(mInput.begin()) { }
-       int getChar() { return (mPos == mInput.end()) ? EOF : *mPos++; }
+       int getChar() { return (mPos == mInput.end()) ? EOF : static_cast<unsigned char>(*mPos++); }
 
 private:
        string mInput;
index b617858180aec950821c5c0701a931bdeb2f92d8..1aa31968cd206b8900f063ce260ec37977f9d9e0 100644 (file)
@@ -363,6 +363,45 @@ CFDataRef BundleDiskRep::component(CodeDirectory::SpecialSlot slot)
        }
 }
 
+BundleDiskRep::RawComponentMap BundleDiskRep::createRawComponents()
+{
+       RawComponentMap map;
+
+       /* Those are the slots known to BundleDiskReps.
+        * Unlike e.g. MachOReps, we cannot handle unknown slots,
+        * as we won't know their slot <-> filename mapping.
+        */
+       int const slots[] = {
+               cdCodeDirectorySlot, cdSignatureSlot, cdResourceDirSlot,
+               cdTopDirectorySlot, cdEntitlementSlot, cdEntitlementDERSlot,
+               cdRepSpecificSlot};
+       
+       for (int slot = 0; slot < (int)(sizeof(slots)/sizeof(slots[0])); ++slot) {
+               /* Here, we only handle metaData slots, i.e. slots that
+                * are explicit files in the _CodeSignature directory.
+                * Main executable slots (if the main executable is a
+                * EditableDiskRep) are handled when editing the
+                * main executable's rep explicitly.
+                * There is also an Info.plist slot, which is not a
+                * real part of the code signature.
+                */
+               CFRef<CFDataRef> data = metaData(slot);
+               
+               if (data) {
+                       map[slot] = data;
+               }
+       }
+       
+       for (CodeDirectory::Slot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; ++slot) {
+               CFRef<CFDataRef> data = metaData(slot);
+               
+               if (data) {
+                       map[slot] = data;
+               }
+       }
+       
+       return map;
+}
 
 // Check that all components of this BundleDiskRep come from either the main
 // executable or the _CodeSignature directory (not mix-and-match).
index a166a7e005da15895a42416b8f6ebcb1374d4b17..1333505571445880c5811c74c6d8e69e9af19ebe 100644 (file)
@@ -55,14 +55,16 @@ namespace CodeSigning {
 // if it is in Mach-O format, or in files in a _CodeSignature directory if not.
 // This DiskRep supports resource sealing.
 //
-class BundleDiskRep : public DiskRep {
+class BundleDiskRep : public DiskRep, public EditableDiskRep {
 public:
        BundleDiskRep(const char *path, const Context *ctx = NULL);
        BundleDiskRep(CFBundleRef ref, const Context *ctx = NULL);
        ~BundleDiskRep();
        
        CFDataRef component(CodeDirectory::SpecialSlot slot);
+       RawComponentMap createRawComponents();
        CFDataRef identification();
+       DiskRep *mainExecRep() const { return mExecRep.get(); };
        std::string mainExecutablePath();
        CFURLRef copyCanonicalPath();
        std::string resourcesRootPath();
index e3c4240ddb68e1e0d96c686ce9e8e048f9a0818f..7fefc1c5e190a2363215dbb455340450a7bec8db 100644 (file)
@@ -80,13 +80,18 @@ void CodeDirectory::Builder::executable(string path,
 
 void CodeDirectory::Builder::reopen(string path, size_t offset, size_t length)
 {
-       assert(mExec);                                  // already called executable()
+       assert(opened());                                       // already called executable()
        mExec.close();
        mExec.open(path);
        mExecOffset = offset;
        mExecLength = length;
 }
 
+bool CodeDirectory::Builder::opened()
+{
+       return bool(mExec);
+}
+
 
 //
 // Set the source for one special slot
index 7872fd58a2c1afb2ea885109ecd8815aaf2053bd..7137444ce9a3e7798f315a1d6eb8d97f79d6aa4b 100644 (file)
@@ -49,6 +49,7 @@ public:
        
        void executable(string path, size_t pagesize, size_t offset, size_t length);
        void reopen(string path, size_t offset, size_t length);
+       bool opened();
 
        void specialSlot(SpecialSlot slot, CFDataRef data);
        void identifier(const std::string &code) { mIdentifier = code; }
index 7595bd5207aeae6af6840c9c0bdde5f0ba3e798d..0d1c485227beecaa86e2cccb9361ca4d63a95b69 100644 (file)
@@ -106,7 +106,7 @@ SecCode *KernelCode::locateGuest(CFDictionaryRef attributes)
                                        MacOSError::throwMe(errSecCSInvalidAttributeValues);
 
                        try {
-                               diskRep = new PidDiskRep(pid, infoPlist);
+                               diskRep = new PidDiskRep(pid, audit, infoPlist);
                        } catch (...) { }
        }
        
index 1e38473b944a6e57a4d729796df4f1435ed76e6a..f26e1c7874f709257fb2fbb4630f3f6fd38db261 100644 (file)
@@ -38,7 +38,7 @@ namespace CodeSigning {
 
 //
 // A SecCode that represents a running UNIX process.
-// Processes are identified by pid.
+// Processes are identified by pid and audit token.
 //
 // ProcessCode inherits GenericCode's access to the cshosting Mach protocol to
 // deal with guests.
index cf90ae61f5487e4f90a1663bed6e6a0217b5b9f7..069cb95f8c396708542ccc7d352070c068232096 100644 (file)
@@ -158,6 +158,27 @@ public:
        static const size_t monolithicPageSize = 0;             // default page size for non-Mach-O executables
 };
 
+/*
+ * Editable Disk Reps allow editing of their existing code signature.
+ * Specifically, they allow for individual components to be replaced,
+ * while preserving all other components.
+ * Lots of restrictions apply, e.g. machO signatures' superblobs may
+ * not change in size, and components covered by the code directory
+ * cannot be replaced without adjusting the code directory.
+ * Replacing or adding CMS blobs (having reserved enough size in the
+ * superblob beforehand) is the original reason this trait exists.
+ */
+class EditableDiskRep {
+public:
+       typedef std::map<CodeDirectory::Slot, CFCopyRef<CFDataRef>> RawComponentMap;
+       
+       /* Return all components in raw form.
+        * Signature editing will add all the components obtained hereby
+        * back to their specific slots, though some of them may have
+        * been replaced in the map.
+        */
+       virtual RawComponentMap createRawComponents() = 0;
+};
 
 //
 // Write-access objects.
index 6986c7251fa7028358a30783d9d9124ffbb6276f..02e7faa8bae1baf03095e2fbe53a462a135aab93 100644 (file)
@@ -265,6 +265,21 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot)
        }
 }
 
+//
+// Retrieve all components, used for signature editing.
+//
+EditableDiskRep::RawComponentMap MachORep::createRawComponents()
+{
+       EditableDiskRep::RawComponentMap  blobMap;
+       const EmbeddedSignatureBlob &blobs = *signingData();
+       
+       for (unsigned int i = 0; i < blobs.count(); ++i) {
+               CodeDirectory::Slot slot = blobs.type(i);
+               const BlobCore *blob = blobs.blob(i);
+               blobMap[slot] = blobs.blobData(slot, blob);
+       }
+       return blobMap;
+}
 
 // Retrieve a component from the embedded signature SuperBlob (if present).
 // This reads the entire signing SuperBlob when first called for an executable,
@@ -275,6 +290,18 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot)
 // calls wouldn't be slower in the end.
 //
 CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot)
+{
+       if (signingData()) {
+               return signingData()->component(slot);
+       }
+       
+       // not found
+       return NULL;
+}
+       
+       
+
+EmbeddedSignatureBlob *MachORep::signingData()
 {
        if (!mSigningData) {            // fetch and cache
                auto_ptr<MachO> macho(mainExecutableImage()->architecture());
@@ -284,20 +311,16 @@ CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot)
                                size_t length = macho->flip(cs->datasize);
                                if ((mSigningData = EmbeddedSignatureBlob::readBlob(macho->fd(), macho->offset() + offset, length))) {
                                        secinfo("machorep", "%zd signing bytes in %d blob(s) from %s(%s)",
-                                               mSigningData->length(), mSigningData->count(),
-                                               mainExecutablePath().c_str(), macho->architecture().name());
+                                                       mSigningData->length(), mSigningData->count(),
+                                                       mainExecutablePath().c_str(), macho->architecture().name());
                                } else {
                                        secinfo("machorep", "failed to read signing bytes from %s(%s)",
-                                               mainExecutablePath().c_str(), macho->architecture().name());
+                                                       mainExecutablePath().c_str(), macho->architecture().name());
                                        MacOSError::throwMe(errSecCSSignatureInvalid);
                                }
                        }
        }
-       if (mSigningData)
-               return mSigningData->component(slot);
-       
-       // not found
-       return NULL;
+       return mSigningData;
 }
 
 
index 69d089a638fa14d1b1ef3065aee7ad05fedd4492..ef2181bb6dddb9011387019f1d7f927ed5d300c7 100644 (file)
@@ -45,12 +45,13 @@ namespace CodeSigning {
 // that it's driven directly from the signing code, with no
 // abstractions to get in the way.
 //
-class MachORep : public SingleDiskRep {
+class MachORep : public SingleDiskRep, public EditableDiskRep {
 public:
        MachORep(const char *path, const Context *ctx = NULL);
        virtual ~MachORep();
        
        CFDataRef component(CodeDirectory::SpecialSlot slot);
+       RawComponentMap createRawComponents();
        CFDataRef identification();
        Universal *mainExecutableImage();
        void prepareForSigning(SigningContext &context);
@@ -86,9 +87,10 @@ protected:
 
 private:
        static bool needsExecSeg(const MachO& macho);
+       EmbeddedSignatureBlob *signingData();
 
        Universal *mExecutable; // cached Mach-O/Universal reference to mainExecutablePath()
-       EmbeddedSignatureBlob *mSigningData; // cached signing data from current architecture
+       mutable EmbeddedSignatureBlob *mSigningData; // cached signing data from current architecture
 };
 
 
index 76d785dca6aa07ae012187a9e0e7110024d7fea6..0aeeb81e1123f650a21396d802f17f5ededf3874 100644 (file)
@@ -58,8 +58,12 @@ PidDiskRep::fetchData(void)
        assert(request != NULL);
        xpc_dictionary_set_string(request, "command", "fetchData");
        xpc_dictionary_set_int64(request, "pid", mPid);
+       
+       if (mAudit) {
+               xpc_dictionary_set_data(request, "audit", mAudit.get(), sizeof(audit_token_t));
+       }
        xpc_dictionary_set_data(request, "infohash", CFDataGetBytePtr(mInfoPlistHash), CFDataGetLength(mInfoPlistHash));
-        
+       
        xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request);
        if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
                const void *data;
@@ -89,20 +93,30 @@ PidDiskRep::fetchData(void)
 }
 
 
-PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist)
+PidDiskRep::PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist)
        : mDataFetched(false)
 {
         BlobCore header;
-        CODESIGN_DISKREP_CREATE_KERNEL(this);
-        
+       
         mPid = pid;
         mInfoPlist = infoPlist;
-
-//        fetchData();
     
-        int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
+        if (audit != NULL) {
+            mAudit.reset(new audit_token_t);
+            memcpy(mAudit.get(), audit, sizeof(audit_token_t));
+        }
+    
+        //        fetchData();
+    
+        int rcent = EINVAL;
+       
+        if (audit != NULL) {
+            rcent = ::csops_audittoken(pid, CS_OPS_BLOB, &header, sizeof(header), mAudit.get());
+        } else {
+            rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
+        }
         if (rcent == 0)
-                MacOSError::throwMe(errSecCSNoSuchCode);
+            MacOSError::throwMe(errSecCSNoSuchCode);
         
         if (errno != ERANGE)
                 UnixError::throwMe(errno);
@@ -112,8 +126,12 @@ PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist)
         
         uint32_t bufferLen = (uint32_t)header.length();
         mBuffer = new uint8_t [bufferLen];
-        
-        UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
+    
+        if (audit != NULL) {
+            UnixError::check(::csops_audittoken(pid, CS_OPS_BLOB, mBuffer, bufferLen, mAudit.get()));
+        } else {
+            UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
+        }
 
         const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer;
         if (!b->validateBlob(bufferLen))
@@ -185,6 +203,7 @@ UnixPlusPlus::FileDesc &PidDiskRep::fd()
 string PidDiskRep::mainExecutablePath()
 {
         char path[MAXPATHLEN * 2];
+        // This is unsafe by pid only, but so is using that path in general.
         if(::proc_pidpath(mPid, path, sizeof(path)) == 0)
                UnixError::throwMe(errno);
 
@@ -194,12 +213,19 @@ string PidDiskRep::mainExecutablePath()
 bool PidDiskRep::appleInternalForcePlatform() const
 {
        uint32_t flags = 0;
-       int rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags));
-
+       int rcent = EINVAL;
+       
+       if (mAudit != NULL) {
+               rcent = ::csops_audittoken(mPid, CS_OPS_STATUS, &flags, sizeof(flags),
+                                                                  mAudit.get());
+       } else {
+               rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags));
+       }
+       
        if (rcent != 0) {
                MacOSError::throwMe(errSecCSNoSuchCode);
        }
-
+       
        return (flags & CS_PLATFORM_BINARY) == CS_PLATFORM_BINARY;
 }
                 
index a530984e7922f6d8b92b85f3b9c84a399fa21a22..c58430099d5d180123fb9b82bd345edb0b6de780 100644 (file)
 #ifndef _H_PIDDISKREP
 #define _H_PIDDISKREP
 
+#include <memory>
+
 #include "diskrep.h"
 
 namespace Security {
 namespace CodeSigning {
                 
                 
-//
-// A KernelDiskRep represents a (the) kernel on disk.
-// It has no write support, so we can't sign the kernel,
-// which is fine since we unconditionally trust it anyway.
-//
 class PidDiskRep : public DiskRep {
 public:
-        PidDiskRep(pid_t pid, CFDataRef infoPlist);
+        PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist);
         ~PidDiskRep();
         
         CFDataRef component(CodeDirectory::SpecialSlot slot);
@@ -64,6 +61,7 @@ private:
         const BlobCore *blob() { return (const BlobCore *)mBuffer; }
         void fetchData(void);
         pid_t mPid;
+        std::unique_ptr<audit_token_t> mAudit;
         uint8_t *mBuffer;
                CFRef<CFDataRef> mInfoPlistHash;
         CFRef<CFDataRef> mInfoPlist;
index 6e7cf0285319e2ef9398677b6979ba8fdd14d11e..ecac7081deb6c68bdaf74de6018af95b59e996fa 100644 (file)
@@ -34,17 +34,24 @@ namespace CodeSigning {
 
 CFDataRef EmbeddedSignatureBlob::component(CodeDirectory::SpecialSlot slot) const
 {
-       if (const BlobCore *blob = this->find(slot)) {
-               if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) {
-                       return makeCFData(*blob);       // is a native Blob
-               } else if (const BlobWrapper *wrap = BlobWrapper::specific(blob)) {
-                       return makeCFData(*wrap);
-               } else {
-                       MacOSError::throwMe(errSecCSSignatureInvalid);
-               }
+       const BlobCore *blob = this->find(slot);
+       
+       if (blob) {
+               return blobData(slot, blob);
        }
        return NULL;
 }
+       
+CFDataRef EmbeddedSignatureBlob::blobData(CodeDirectory::SpecialSlot slot, BlobCore const *blob)
+{
+       if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) {
+               return makeCFData(*blob);       // is a native Blob
+       } else if (const BlobWrapper *wrap = BlobWrapper::specific(blob)) {
+               return makeCFData(*wrap);
+       } else {
+               MacOSError::throwMe(errSecCSSignatureInvalid);
+       }
+}
 
 
 void EmbeddedSignatureBlob::Maker::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
index eed6b5c5c1325d718c45333fd9935eea28285c49..392e840416d012b361e3df903f15fd6675804214 100644 (file)
@@ -43,6 +43,7 @@ namespace CodeSigning {
 class EmbeddedSignatureBlob : public SuperBlobCore<EmbeddedSignatureBlob, 0xfade0cc0, uint32_t> {
        typedef SuperBlobCore<EmbeddedSignatureBlob, 0xfade0cc0, uint32_t> _Core;
 public:
+       static CFDataRef blobData(CodeDirectory::SpecialSlot slot, BlobCore const *blob);
        CFDataRef component(CodeDirectory::SpecialSlot slot) const;
        
        class Maker : public _Core::Maker {
index 9e81b53a1219468f8484564d8e85bbebfee65c15..b5f07c40ce5e92c738ddcf10a4d5c088d84d6e71 100644 (file)
@@ -24,6 +24,7 @@
 //
 // signer - Signing operation supervisor and controller
 //
+#include "bundlediskrep.h"
 #include "der_plist.h"
 #include "signer.h"
 #include "resources.h"
@@ -205,7 +206,8 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags)
        }
        if (!haveCdFlags)
                cdFlags = 0;
-       if (state.mSigner == SecIdentityRef(kCFNull))   // ad-hoc signing requested...
+       if ((state.mSigner == SecIdentityRef(kCFNull)) &&
+               !state.mOmitAdhocFlag)  // ad-hoc signing requested...
                cdFlags |= kSecCodeSignatureAdhoc;      // ... so note that
 
        // prepare the internal requirements input
@@ -996,5 +998,207 @@ void SecCodeSigner::Signer::cookEntitlements(CFDataRef entitlements, bool genera
        }
 }
 
+//// Signature Editing
+       
+void SecCodeSigner::Signer::edit(SecCSFlags flags)
+{
+       rep = code->diskRep()->base();
+       
+       Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage();
+       
+       prepareForEdit(flags);
+       
+       if (fat != NULL) {
+               editMachO(fat);
+       } else {
+               editArchitectureAgnostic();
+       }
+}
+
+EditableDiskRep *SecCodeSigner::Signer::editMainExecutableRep(DiskRep *rep)
+{
+       EditableDiskRep *mainExecRep = NULL;
+       BundleDiskRep *bundleDiskRep = dynamic_cast<BundleDiskRep*>(rep);
+       
+       if (bundleDiskRep) {
+               mainExecRep = dynamic_cast<EditableDiskRep*>(bundleDiskRep->mainExecRep());
+       }
+       
+       return mainExecRep;
+}
+       
+void SecCodeSigner::Signer::prepareForEdit(SecCSFlags flags) {
+       setDigestAlgorithms(code->hashAlgorithms());
+       
+       Universal *machO = (code->diskRep()->mainExecutableIsMachO() ?
+                                               code->diskRep()->mainExecutableImage() : NULL);
+       
+       /* We need at least one architecture in all cases because we index our
+        * RawComponentMaps by architecture. However, only machOs have any
+        * architecture at all, for generic targets there will just be one
+        * RawComponentMap.
+        * So if the main executable is not a machO, we just choose the local
+        * (signer's) main architecture as dummy value for the first element in our pair. */
+       editMainArch = (machO != NULL ? machO->bestNativeArch() : Architecture::local());
+
+       if (machO != NULL) {
+               if (machO->narrowed()) {
+                       /* --arch gives us a narrowed SecStaticCode, but because
+                        * codesign_allocate always creates or replaces signatures
+                        * for all slices, we must operate on the universal
+                        * SecStaticCode. Instead, we provide --edit-arch to specify
+                        * which slices to edit, the others have their code signature
+                        * copied without modifications.
+                        */
+                       MacOSError::throwMe(errSecCSNotSupported,
+                                                               "Signature editing must be performed on universal binary instead of narrow slice (using --edit-arch instead of --arch).");
+               }
+
+               if (state.mEditArch && !machO->isUniversal()) {
+                       MacOSError::throwMe(errSecCSInvalidFlags,
+                                                               "--edit-arch is only valid for universal binaries.");
+               }
+               
+               if (state.mEditCMS && machO->isUniversal() && !state.mEditArch) {
+                       /* Each slice has its own distinct code signature,
+                        * so a CMS blob is only valid for its one slice.
+                        * Therefore, replacing all CMS blobs in all slices
+                        * with the same blob is rather nonsensical, and we refuse.
+                        *
+                        * (Universal binaries with only one slice can exist,
+                        * and in that case the slice to operate on would be
+                        * umambiguous, but we are not treating those binaries
+                        * specially and still want --edit-arch for consistency.)
+                        */
+                       MacOSError::throwMe(errSecCSNotSupported,
+                                                               "CMS editing must be performed on specific slice (specified with --edit-arch).");
+               }
+       }
+       
+       void (^editArch)(SecStaticCode *code, Architecture arch) =
+       ^(SecStaticCode *code, Architecture arch) {
+               EditableDiskRep *editRep = dynamic_cast<EditableDiskRep *>(code->diskRep());
+               
+               if (editRep == NULL) {
+                       MacOSError::throwMe(errSecCSNotSupported,
+                                                               "Signature editing not supported for code of this type.");
+               }
+               
+               EditableDiskRep *mainExecRep = editMainExecutableRep(code->diskRep());
+               
+               if (mainExecRep != NULL) {
+                       // Delegate editing to the main executable if it is an EditableDiskRep.
+                       //(Which is the case for machOs.)
+                       editRep = mainExecRep;
+               }
+
+               editComponents[arch] = std::make_unique<RawComponentMap>(editRep->createRawComponents());
+               
+               if (!state.mEditArch || arch == state.mEditArch) {
+                       if (state.mEditCMS) {
+                               CFDataRef cms = state.mEditCMS.get();
+                               (*editComponents[arch])[cdSignatureSlot] = cms;
+                       }
+               }
+       };
+       
+       editArch(code, editMainArch);
+       
+       code->handleOtherArchitectures(^(Security::CodeSigning::SecStaticCode *subcode) {
+               Universal *fat = subcode->diskRep()->mainExecutableImage();
+               assert(fat && fat->narrowed()); // handleOtherArchitectures gave us a focused architecture slice.
+               Architecture arch = fat->bestNativeArch();      // actually, only architecture for this slice.
+               editArch(subcode, arch);
+       });
+       
+       /* The resource dictionary is special, because it is
+        * considered "global" instead of per architecture.
+        * For editing, that means it's usually not embedded
+        * in the main executable's signature if it exists,
+        * but in the containing disk rep (e.g. the
+        * CodeResources file if the rep is a Bundle).
+        */
+       resourceDictData = rep->component(cdResourceDirSlot);
+}
+       
+void SecCodeSigner::Signer::editMachO(Universal *fat) {
+       // Mach-O executable at the core - perform multi-architecture signature editing
+       RefPointer<DiskRep::Writer> writer = rep->writer();
+       
+       if (state.mPreserveAFSC)
+               writer->setPreserveAFSC(state.mPreserveAFSC);
+       
+       unique_ptr<ArchEditor> editor(new MachOEditor(writer, *fat,
+                                                                                                 this->digestAlgorithms(),
+                                                                                                 rep->mainExecutablePath()));
+       assert(editor->count() > 0);
+       
+       if (resourceDictData && !editor->attribute(writerNoGlobal)) {
+               // For when the resource dict is "global", e.g. for bundles.
+               editor->component(cdResourceDirSlot, resourceDictData);
+       }
+       
+       for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) {
+               MachOEditor::Arch &arch = *it->second;
+               arch.source.reset(fat->architecture(it->first)); // transfer ownership
+               
+               if (resourceDictData && editor->attribute(writerNoGlobal)) {
+                       // Technically possible to embed a resource dict in the embedded sig.
+                       arch.component(cdResourceDirSlot, resourceDictData);
+               }
+               
+               for (auto const &entry : *editComponents[arch.architecture]) {
+                       CodeDirectory::Slot slot = entry.first;
+                       CFDataRef data = entry.second.get();
+                       arch.component(slot, data);
+               }
+               
+               /* We must preserve the original superblob's size, as the size is
+                * also in the macho's load commands, which are itself covered
+                * by the signature. */
+               arch.blobSize = arch.source->signingLength();
+       }
+       
+       editor->allocate();
+       
+       for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) {
+               MachOEditor::Arch &arch = *it->second;
+               editor->reset(arch);
+               
+               if (!state.mDryRun) {
+                       EmbeddedSignatureBlob *blob = arch.make();
+                       editor->write(arch, blob);      // takes ownership of blob
+               }
+       }
+       
+       if (!state.mDryRun) {
+               editor->commit();
+       }
+
+}
+
+void SecCodeSigner::Signer::editArchitectureAgnostic()
+{
+       if (state.mDryRun) {
+               return;
+
+       }
+       // non-Mach-O executable - single-instance signature editing
+       RefPointer<DiskRep::Writer> writer = rep->writer();
+       
+       if(state.mPreserveAFSC)
+               writer->setPreserveAFSC(state.mPreserveAFSC);
+       
+       for (auto const &entry : *editComponents[editMainArch]) {
+               CodeDirectory::Slot slot = entry.first;
+               CFDataRef data = entry.second.get();
+               
+               writer->component(slot, data);
+       }
+
+       // commit to storage
+       writer->flush();
+}
+
 } // end namespace CodeSigning
 } // end namespace Security
index f43494f04b77b14501cc8098990f6c8f82c25a57..960cf7960785c7b6f92aac8bcde3d3e83801d1bb 100644 (file)
@@ -51,6 +51,7 @@ public:
 
        void sign(SecCSFlags flags);
        void remove(SecCSFlags flags);
+       void edit(SecCSFlags flags);
        
        SecCodeSigner &state;
        SecStaticCode * const code;
@@ -66,6 +67,10 @@ protected:
        void prepare(SecCSFlags flags);                         // set up signing parameters
        void signMachO(Universal *fat, const Requirement::Context &context); // sign a Mach-O binary
        void signArchitectureAgnostic(const Requirement::Context &context); // sign anything else
+       
+       void prepareForEdit(SecCSFlags flags);          // set up signature editing
+       void editMachO(Universal *fat);                         // edit a Mach-O binary
+       void editArchitectureAgnostic();                        // edit anything else
 
        // HashAlgorithm -> PreEncrypt hashes
        typedef std::map<CodeDirectory::HashAlgorithm, CFCopyRef<CFDataRef> >
@@ -79,6 +84,10 @@ protected:
        // Architecture -> RuntimeVersionMap
        typedef std::map<Architecture, RuntimeVersionMap>
                RuntimeVersionMaps;
+       // Architecture -> RawComponentMap
+       typedef EditableDiskRep::RawComponentMap RawComponentMap;
+       typedef std::map<Architecture, std::unique_ptr<RawComponentMap>>
+               RawComponentMaps;
 
        void populate(DiskRep::Writer &writer);         // global
        void populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer,
@@ -101,6 +110,8 @@ protected:
        SecCSFlags signingFlags() const;
        
 private:
+       static EditableDiskRep *editMainExecutableRep(DiskRep *rep);
+       
        void addPreEncryptHashes(PreEncryptHashMap &map, SecStaticCode const *code);
        void addRuntimeVersions(RuntimeVersionMap &map, SecStaticCode const *code);
        
@@ -137,6 +148,10 @@ private:
        bool strict;                                    // strict validation
        bool generateEntitlementDER;    // generate entitlement DER
        
+       // Signature Editing
+       Architecture editMainArch;              // main architecture for editing
+       RawComponentMaps editComponents; // components for signature
+       
 private:
        Mutex resourceLock;
 };
index ec0cf4835045046971d8ec16f2e631152927eee3..f6da5e936cd7142612990322bafe4659a46568b7 100644 (file)
@@ -262,7 +262,11 @@ void MachOEditor::reset(Arch &arch)
 
        for (auto type = mHashTypes.begin(); type != mHashTypes.end(); ++type) {
                arch.eachDigest(^(CodeDirectory::Builder& builder) {
-                       builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset());
+                       /* Signature editing may have no need for cd builders, and not
+                        * have opened them, so only reopen them conditionally. */
+                       if (builder.opened()) {
+                               builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset());
+                       }
                });
        }
 }
index 53c6e51f3ad0d3003bd19221888be01ecb294255..1bd01d8ce9d92a53e5f6b5c29a60f12cb30550e2 100644 (file)
@@ -86,7 +86,7 @@ public:
 
 //
 // A multi-architecture editing assistant.
-// ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture
+// ArchEditor collects (Mach-O) architectures in use, and maintains per-architecture
 // data structures. It must be subclassed to express a particular way to handle the signing
 // data.
 //
index 4fd99c702847379cc4d101defe9d2a1b5fe8a6cc..2886f22ca964b055cbc18bb338514887bc6c94c8 100644 (file)
@@ -418,6 +418,11 @@ class RequirementLexer extends Lexer;
 options {
        k=2;
        testLiterals=false;
+
+    // Pass through valid UTF-8 (which excludes hex C0-C1 and F5-FF),
+       // but also exclude ASCII control characters below 0x20 (space).
+       // Byte ranges according to Unicode 11.0, paragraph 3.9 D92.
+       charVocabulary='\000'..'\277' | '\302'..'\364';
 }
 
 protected
index 3cd84cc4e83b96334e55845656b6eeb86cc9ac17..aa168bd8b3d257f6b514296606b21580078e1dda 100644 (file)
@@ -1034,6 +1034,12 @@ DLDbListCFPref::defaultDLDbIdentifier()
             if (mDefaultDLDbIdentifier.mImpl != NULL && actualIdentifier.mImpl != NULL)
             {
                 st_result = stat(actualIdentifier.dbName(), &st);
+
+                // Always claim that the system keychain exists for purposes of the search list
+                if (st_result && 0 == strncmp(actualIdentifier.dbName(), kSystemKeychainPath, strlen(kSystemKeychainPath))) {
+                    secnotice("secpref", "System keychain (%s) does not exist. Continuing as if it does...", actualIdentifier.dbName());
+                    st_result = 0;
+                }
             }
 
             if (st_result)
index 2ec227ef090dee51d57673381f5aea79654ca951..bea27fec5077ffe1e6476bb256615fbd9c18aec4 100644 (file)
@@ -640,7 +640,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes*
             return false; // No MAC, no integrity.
         }
 
-        throw cssme;
+        throw;
     }
 
     secnotice("integrity", "***** INVALID ITEM");
@@ -1833,7 +1833,7 @@ ItemImpl::getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData)
                 }
             } catch(CssmError cssme) {
                 secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what());
-                throw cssme;
+                throw;
             }
 
                        SSDbUniqueRecordImpl* impl = dynamic_cast<SSDbUniqueRecordImpl *>(&(*dbUniqueRecord()));
index 04095492f77283bcae1e8a75598a7ec69647fab0..fed9dae0607ca31255587013a143ef23a3f71e4f 100644 (file)
@@ -489,7 +489,7 @@ KeyItem::key()
         } catch(CssmError cssme) {
             mKey.release();
             secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what());
-            throw cssme;
+            throw;
         }
     }
 
index e3ce4cb0650e25fc49dfaa8f5b381c7522cfc0c0..2b125fa8ec7aeee2d97e88b98102e1dc20391db2 100644 (file)
@@ -656,11 +656,14 @@ KeychainImpl::changePassphrase(UInt32 oldPasswordLength, const void *oldPassword
        UInt32 newPasswordLength, const void *newPassword)
 {
        StLock<Mutex>_(mMutex);
-       
+
+    secnotice("KCspi", "Attempting to change passphrase for %s", mDb->name());
+
        bool isSmartcard =      (mDb->dl()->guid() == gGuidAppleSdCSPDL);
 
        TrackingAllocator allocator(Allocator::standard());
        AutoCredentials cred = AutoCredentials(allocator);
+
        if (oldPassword)
        {
                const CssmData &oldPass = *new(allocator) CssmData(const_cast<void *>(oldPassword), oldPasswordLength);
index bb3adfc6712bd6dae0801072eaca95785c41a9f6..301cf0e52eea15b3b5f84e800b9b94bfc5ba3241 100644 (file)
@@ -323,8 +323,7 @@ SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAcce
 
     CFIndex rightsSize = numAcls > 0 ? numAcls : 1;
 
-       CSSM_ACL_AUTHORIZATION_TAG rights[rightsSize];
-       memset(rights, 0, sizeof(rights));
+       std::vector<CSSM_ACL_AUTHORIZATION_TAG> rights(numAcls);
 
        for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++)
        {
@@ -384,7 +383,7 @@ SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAcce
                                { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
                                false,  // Delegate
                                // rights for this entry
-                               { (uint32)numAcls, rights },
+                               { (uint32)numAcls, rights.data() },
                                // rest is defaulted
                        }
                }
index ab0419a2e464507d53fbbfa29ac25c09945d37d8..ad88d453afc834ecf5df225ce809a9e14d666af6 100644 (file)
@@ -548,13 +548,10 @@ _ConvertNewFormatToOldFormat(
 
        // make storage to extract the dictionary items
        CFIndex itemsInDictionary = CFDictionaryGetCount(dictionaryRef);
-       CFTypeRef keys[itemsInDictionary];
-       CFTypeRef values[itemsInDictionary];
+       std::vector<CFTypeRef> keys(itemsInDictionary);
+       std::vector<CFTypeRef> values(itemsInDictionary);
 
-       CFTypeRef *keysPtr = keys;
-       CFTypeRef *valuesPtr = values;
-
-       CFDictionaryGetKeysAndValues(dictionaryRef, keys, values);
+       CFDictionaryGetKeysAndValues(dictionaryRef, keys.data(), values.data());
 
        // count the number of items we are interested in
        CFIndex count = 0;
@@ -562,12 +559,12 @@ _ConvertNewFormatToOldFormat(
 
        // since this is one of those nasty order n^2 loops, we cache as much stuff as possible so that
        // we don't pay the price for this twice
-       SecKeychainAttrType tags[itemsInDictionary];
-       ItemRepresentation types[itemsInDictionary];
+       std::vector<SecKeychainAttrType> tags(itemsInDictionary);
+       std::vector<ItemRepresentation> types(itemsInDictionary);
 
        for (i = 0; i < itemsInDictionary; ++i)
        {
-               CFTypeRef key = keysPtr[i];
+               CFTypeRef key = keys[i];
 
                int j;
                for (j = 0; j < infoNumItems; ++j)
@@ -584,7 +581,7 @@ _ConvertNewFormatToOldFormat(
                if (j >= infoNumItems)
                {
                        // if we got here, we aren't interested in this item.
-                       valuesPtr[i] = NULL;
+                       values[i] = NULL;
                }
        }
 
@@ -602,7 +599,7 @@ _ConvertNewFormatToOldFormat(
 
                        // we have to clone the data pointer.  The caller will need to make sure to throw these away
                        // with _FreeAttrList when it is done...
-                       attrList->attr[resultPointer].data = CloneDataByType(types[i], valuesPtr[i], attrList->attr[resultPointer].length);
+                       attrList->attr[resultPointer].data = CloneDataByType(types[i], values[i], attrList->attr[resultPointer].length);
                        resultPointer += 1;
                }
        }
@@ -2364,19 +2361,6 @@ _ReplaceKeychainItem(
        for (i=0, newCount=0; i < attrList->count; i++) {
                if (attrList->attr[i].length > 0) {
                        newAttrList.attr[newCount++] = attrList->attr[i];
-               #if 0
-                       // debugging code to log item attributes
-                       SecKeychainAttrType tag = attrList->attr[i].tag;
-                       SecKeychainAttrType htag=(SecKeychainAttrType)OSSwapConstInt32(tag);
-                       char tmp[sizeof(SecKeychainAttrType) + 1];
-                       char tmpdata[attrList->attr[i].length + 1];
-                       memcpy(tmp, &htag, sizeof(SecKeychainAttrType));
-                       tmp[sizeof(SecKeychainAttrType)]=0;
-                       memcpy(tmpdata, attrList->attr[i].data, attrList->attr[i].length);
-                       tmpdata[attrList->attr[i].length]=0;
-                       secitemlog(priority, "item attr '%s' = %d bytes: \"%s\"",
-                               tmp, (int)attrList->attr[i].length, tmpdata);
-               #endif
                }
        }
        newAttrList.count = newCount;
diff --git a/OSX/libsecurity_keychain/regressions/kc-45-change-password.c b/OSX/libsecurity_keychain/regressions/kc-45-change-password.c
new file mode 100644 (file)
index 0000000..c944f79
--- /dev/null
@@ -0,0 +1,33 @@
+#include <Security/SecKeychain.h>
+#include <Security/SecKeychainPriv.h>
+
+#include "keychain_regressions.h"
+#include "kc-helpers.h"
+
+int kc_45_change_password(int argc, char *const *argv)
+{
+    plan_tests(14);
+
+    initializeKeychainTests(__FUNCTION__);
+
+    ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "SecKeychainSetUserInteractionAllowed(FALSE)");
+
+    SecKeychainRef keychain = createNewKeychain("test", "before");
+    ok_status(SecKeychainLock(keychain), "SecKeychainLock");
+    is_status(SecKeychainChangePassword(keychain, 0, NULL, 5, "after"), errSecAuthFailed, "Change PW w/ null pw while locked");
+    is_status(SecKeychainChangePassword(keychain, 5, "badpw", 5, "after"), errSecAuthFailed, "Change PW w/ bad pw while locked");
+    ok_status(SecKeychainUnlock(keychain, 6, "before", true), "SecKeychainUnlock");
+    is_status(SecKeychainChangePassword(keychain, 0, NULL, 5, "after"), errSecAuthFailed, "Change PW w/ null pw while unlocked");
+    is_status(SecKeychainChangePassword(keychain, 5, "badpw", 5, "after"), errSecAuthFailed, "Change PW w/ bad pw while unlocked");
+
+    ok_status(SecKeychainChangePassword(keychain, 6, "before", 7, "between"), "Change PW w/ good pw while unlocked");
+    ok_status(SecKeychainLock(keychain), "SecKeychainLock");
+    ok_status(SecKeychainChangePassword(keychain, 7, "between", 7, "after"), "Change PW w/ good pw while locked");
+    checkPrompts(0, "Unexpected keychain access prompt");
+
+    ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
+    CFRelease(keychain);
+
+    deleteTestFiles();
+    return 0;
+}
index b9ae13c90012d2a448a7ffa157af2997688ca950..7599d26c176ecb4eef6ee02017ba49f4b93d4d9e 100644 (file)
@@ -44,6 +44,7 @@ ONE_TEST(kc_41_sececkey)
 ONE_TEST(kc_42_trust_revocation)
 ONE_TEST(kc_43_seckey_interop)
 ONE_TEST(kc_44_secrecoverypassword)
+ONE_TEST(kc_45_change_password)
 ONE_TEST(si_20_sectrust_provisioning)
 ONE_TEST(si_33_keychain_backup)
 ONE_TEST(si_34_one_true_keychain)
index 6b337e26143f550d9ad6c9b1be2f27daf0e22acd..29c8a0d06e0f22b0d31980e9f64597135c03dfc6 100644 (file)
@@ -396,9 +396,9 @@ int main(int argc, const char *argv[])
     }
     
     // make storage for the real path
-    char buffer[total_length];
-    strlcpy(buffer, home_dir, total_length);
-    strlcat(buffer, g_path_to_plist, total_length);
+    char buffer[PATH_MAX];
+    strlcpy(buffer, home_dir, sizeof(buffer));
+    strlcat(buffer, g_path_to_plist, sizeof(buffer));
     keychain_prefs_path = xpc_string_create(buffer);
     home = xpc_string_create(home_dir);
     
index a173aa139083ebe4356aed9ba1844617d1ecab0e..3d4dc41a80d876b098b31a651ed0960df26ca75f 100644 (file)
@@ -749,8 +749,11 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i,
     CSSM_DATA_PTR contentType, digest;
     OSStatus status, status2;
 
-    cinfo = &(sigd->contentInfo);
+    if (sigd == NULL || sigd->signerInfos == NULL || i >= SecCmsSignedDataSignerInfoCount(sigd)) {
+        return errSecParam;
+    }
 
+    cinfo = &(sigd->contentInfo);
     signerinfo = sigd->signerInfos[i];
 
     /* Signature or digest level verificationStatus errors should supercede
@@ -759,19 +762,19 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i,
     /* Find digest and contentType for signerinfo */
     algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo);
     if (algiddata == NULL) {
-        return errSecInternalError; // shouldn't have happened, this is likely due to corrupted data
+        return errSecInvalidDigestAlgorithm;
     }
     
     digest = SecCmsSignedDataGetDigestByAlgTag(sigd, algiddata->offset);
-       if(digest == NULL) {
-               /* 
-                * No digests; this probably had detached content the caller has to 
-                * deal with. 
-                * FIXME: need some error return for this (as well as many 
-                * other places in this library).
-                */
-               return errSecDataNotAvailable;
-       }
+    if(digest == NULL) {
+        /*
+         * No digests; this probably had detached content the caller has to
+         * deal with.
+         * FIXME: need some error return for this (as well as many
+         * other places in this library).
+         */
+        return errSecDataNotAvailable;
+    }
     contentType = SecCmsContentInfoGetContentTypeOID(cinfo);
 
     /* verify signature */
index e5e037a16b342a20787529ca3ee17f982140f384..da6677f27bd73a9c2933477cc2d482e5497ba90a 100644 (file)
@@ -393,7 +393,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) {
 
 /* Verifying with attributes goes through a different code path than verifying without,
  * so we need to test both. */
-#define kNumberVerifyTests 12
+#define kNumberVerifyTests 13
 static void verify_tests(SecKeychainRef kc, bool isRsa) {
     /* no attributes */
     is(verify_please(kc, (isRsa) ? rsa_md5 : ec_md5,
@@ -421,6 +421,9 @@ static void verify_tests(SecKeychainRef kc, bool isRsa) {
     /***** Once more, with validation errors *****/
 
     /* no attributes */
+    is(verify_please(kc, (isRsa) ? rsa_sinfo_unknown_digest : ec_sinfo_unknown_digest,
+                     (isRsa) ? sizeof(rsa_sinfo_unknown_digest) : sizeof(ec_sinfo_unknown_digest)),
+       errSecInvalidDigestAlgorithm, "Verify unknown digest OID in signer info");
     is(invalidate_and_verify(kc, (isRsa) ? rsa_md5 : ec_md5,
                      (isRsa) ? sizeof(rsa_md5) : sizeof(ec_md5)),
        SECFailure, "Verify invalid MD5, no attributes");
index dc46feeb33e743212176322059a86f11b97e0af9..371b8f69bdf8d5fa2effe8371f7239003c0131b3 100644 (file)
@@ -233,6 +233,89 @@ unsigned char _ec_identity[] = {
 /*
  * MARK: RSA-signed messages (no attributes)
  */
+unsigned char rsa_sinfo_unknown_digest[] = {
+    0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
+    0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20,
+    0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41,
+    0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+    0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
+    0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53,
+    0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+    0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65,
+    0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63,
+    0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+    0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+    0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06,
+    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
+    0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34,
+    0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, 0x32,
+    0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20,
+    0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70,
+    0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53,
+    0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20,
+    0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11,
+    0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30,
+    0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
+    0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+    0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, 0xf4,
+    0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, 0xb0,
+    0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, 0xf7,
+    0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, 0xcf,
+    0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, 0x54,
+    0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, 0x00,
+    0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, 0xba,
+    0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, 0xb1,
+    0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, 0xad,
+    0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, 0x86,
+    0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, 0x6a,
+    0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, 0x0b,
+    0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, 0x52,
+    0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+    0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, 0xd5,
+    0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, 0x09,
+    0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, 0xbf,
+    0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, 0xa4,
+    0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, 0x94,
+    0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, 0x60,
+    0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, 0x61,
+    0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, 0x77,
+    0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, 0xaf,
+    0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, 0x63,
+    0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, 0x63,
+    0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, 0xa1,
+    0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, 0xca,
+    0x3f, 0xb5, 0x54, 0x31, 0x82, 0x01, 0xdb, 0x30, 0x82, 0x01, 0xd7, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, 0xa7,
+    0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+    0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49,
+    0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+    0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+    0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+    0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x02, 0x20, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+    0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x44, 0x4f, 0x1c, 0x4f, 0x73, 0x46, 0xb4, 0x67, 0x86, 0x53, 0x6e, 0x09, 0x4a, 0x18,
+    0x89, 0x82, 0xb0, 0x9d, 0xf5, 0xa9, 0x81, 0x21, 0x97, 0x2d, 0x1c, 0x61, 0x4a, 0xa0, 0x9a, 0xa1, 0x6d, 0xb0, 0xb2, 0xbe,
+    0xc8, 0x27, 0x4a, 0x0e, 0xbd, 0x52, 0xf2, 0x56, 0x8a, 0xb6, 0x41, 0x45, 0xfc, 0xf6, 0x09, 0xb7, 0x83, 0x89, 0x87, 0xc6,
+    0x5c, 0xfb, 0xe0, 0x22, 0x75, 0x9b, 0xa2, 0x24, 0x65, 0xd0, 0x51, 0xe0, 0xc6, 0x00, 0xad, 0x39, 0x50, 0x84, 0x31, 0x5c,
+    0x63, 0x54, 0x8c, 0x3c, 0xa3, 0x69, 0x7f, 0xb2, 0x2c, 0x60, 0xa1, 0x5d, 0x6a, 0xac, 0xb2, 0x02, 0x26, 0x5b, 0x82, 0x61,
+    0x2e, 0xb0, 0x32, 0xf7, 0x4e, 0xa3, 0x31, 0x00, 0xa7, 0x29, 0x4b, 0xdc, 0x30, 0x7f, 0x33, 0x14, 0x5a, 0xf1, 0x58, 0x5e,
+    0x90, 0x77, 0xf3, 0x9c, 0x68, 0xbe, 0xe9, 0x4c, 0xf6, 0x33, 0x64, 0xdf, 0x3f, 0xf4, 0xb9, 0x6b, 0xd5, 0x54, 0xb8, 0x4a,
+    0x8f, 0xbb, 0xce, 0xde, 0x4a, 0x58, 0x9e, 0xad, 0x67, 0x99, 0xbe, 0xe7, 0x0a, 0x54, 0x2b, 0x19, 0x0c, 0x45, 0x45, 0x41,
+    0x9e, 0x56, 0x07, 0x45, 0x95, 0x56, 0x92, 0xa8, 0xd6, 0x8f, 0xab, 0xb0, 0x9b, 0x39, 0xcb, 0x5a, 0x0d, 0x29, 0x2d, 0x8b,
+    0x53, 0xf4, 0x85, 0xb1, 0xec, 0x6f, 0x95, 0xd2, 0x6e, 0xd5, 0x36, 0x65, 0xd4, 0x30, 0x4d, 0x26, 0x37, 0x8b, 0x06, 0x39,
+    0xf5, 0xe6, 0xde, 0x8c, 0xf0, 0x84, 0x69, 0x96, 0xd7, 0xb9, 0x22, 0x24, 0xf5, 0x74, 0x69, 0x4e, 0x2b, 0xea, 0x9d, 0x5a,
+    0xd7, 0xfc, 0xea, 0x7d, 0x8f, 0xd7, 0x34, 0x7f, 0x4f, 0x8a, 0x5c, 0xb6, 0x73, 0x9a, 0x8f, 0xa0, 0x74, 0x5e, 0xca, 0xdc,
+    0xc9, 0x78, 0x85, 0x46, 0xb8, 0x79, 0x29, 0x10, 0xa5, 0x6c, 0x1e, 0x4e, 0xac, 0xba, 0x8e, 0xa2, 0x2d, 0xf8, 0x40, 0x2d,
+    0xde, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 unsigned char rsa_md5[] = {
     0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
     0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
@@ -750,6 +833,59 @@ unsigned char rsa_sha256_attr[] = {
 /*
  * MARK: EC-signed messages (no attributes)
  */
+unsigned char ec_sinfo_unknown_digest[] = {
+    0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
+    0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20,
+    0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41,
+    0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xa0, 0x82, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+    0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0xa6,
+    0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65,
+    0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+    0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e,
+    0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
+    0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72,
+    0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+    0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70,
+    0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, 0x39,
+    0x35, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81,
+    0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+    0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49,
+    0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+    0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+    0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+    0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, 0x88,
+    0x07, 0x03, 0x42, 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, 0x81,
+    0xa1, 0x4e, 0xc5, 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, 0x6c,
+    0xc4, 0xcd, 0x8c, 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, 0x13,
+    0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+    0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x81,
+    0x1b, 0xed, 0x5a, 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, 0x85,
+    0x7a, 0x2f, 0x65, 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, 0xcb,
+    0xeb, 0xf7, 0x1c, 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, 0xf5,
+    0xbe, 0x85, 0x40, 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x1b, 0x30, 0x82, 0x01, 0x17, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, 0x30,
+    0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20,
+    0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20,
+    0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72,
+    0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20,
+    0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+    0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61,
+    0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x02, 0x20, 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04,
+    0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xa2, 0x9f, 0x73, 0x2d, 0x2a, 0xa0, 0xca, 0xb4, 0xf6, 0xc9, 0xfd, 0x68, 0xd2, 0xe7,
+    0x8d, 0x07, 0xdd, 0x60, 0xcc, 0xe1, 0xb6, 0xfe, 0xa9, 0x11, 0xd8, 0xb7, 0x68, 0xa4, 0xe3, 0xed, 0x1b, 0x42, 0x02, 0x20,
+    0x4b, 0x64, 0x3e, 0xe0, 0x50, 0x29, 0x89, 0x30, 0xd0, 0x32, 0x2d, 0xfc, 0xd3, 0x6b, 0xe8, 0x06, 0x15, 0xe2, 0x91, 0x99,
+    0x7b, 0x26, 0xc4, 0xa3, 0x85, 0xf0, 0x05, 0x95, 0x4d, 0xf9, 0x51, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 unsigned char ec_md5[] = {
     0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
     0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
index bd0aaea64eb7484f011931b9327eec7b9c192bec..e2e9f709ee612515fc7e49c15146fd54ead84b27 100644 (file)
@@ -336,9 +336,9 @@ tests(void)
                 fcntl(sp[1], F_SETNOSIGPIPE, 1);
 
                 bool break_on_req = (j!=0);
-                SSLClientAuthenticationType auth = (k == 0) ? kNeverAuthenticate
-                                                   : (k == 1) ? kTryAuthenticate
-                                                   : kAlwaysAuthenticate;
+                SSLAuthenticate auth = (k == 0) ? kNeverAuthenticate
+                        : (k == 1) ? kTryAuthenticate
+                            : kAlwaysAuthenticate;
 
                 CFArrayRef client_certs = (i == 0) ? NULL
                                           : (i == 1) ? trusted_client_chain()
index 9c99aea556b9b3d15397a2b407721df5350a1d6c..e715b11d3e93756c5903ddc5702c96319a2b034b 100644 (file)
@@ -199,6 +199,12 @@ int MacOSError::unixError() const
 void MacOSError::throwMe(int error)
 { throw MacOSError(error); }
 
+void MacOSError::throwMe(int error, char const *message, ...)
+{
+    // Ignoring the message for now, will do something with it later.
+    throw MacOSError(error);
+}
+
 MacOSError MacOSError::make(int error)
 { return MacOSError(error); }
 
index d3ee946c76ca37fb0a04a8b8137707a388919d93..4baae8f38c3524d745d50f6f11d371b32d9dd1b2 100644 (file)
@@ -100,6 +100,7 @@ public:
     
     static void check(OSStatus status) { if (status != errSecSuccess) throwMe(status); }
     static void throwMe(int err) __attribute__((noreturn));
+    static void throwMe(int err, char const *message, ...) __attribute__((noreturn));
 
     static MacOSError make(int err);
 };
index 29ffa83a3c97936646451b291667abb3192e464b..30408289b788c09693dd86c022324d2968b25f90 100644 (file)
@@ -562,6 +562,9 @@ kern_return_t cdsa_mach_notify_dead_name(mach_port_t, mach_port_name_t port)
                MachServer::active().notifyDeadName(port);
        } catch (...) {
        }
+    // the act of receiving a dead name notification allocates a dead-name
+    // right that must be deallocated
+    mach_port_deallocate(mach_task_self(), port);
        return KERN_SUCCESS;
 }
 
index 6a03d1842f4a77edb333f270edcc6e2ce953196f..99f58033ec4ce5344b1ebd19914e227650490683 100644 (file)
@@ -562,6 +562,7 @@ extern const CFStringRef kCKKSViewAutoUnlock;
 extern const CFStringRef kCKKSViewHealth;
 extern const CFStringRef kCKKSViewApplePay;
 extern const CFStringRef kCKKSViewHome;
+extern const CFStringRef kCKKSViewLimitedPeersAllowed;
 
 
 /*!
index 41449d5938868d61bd3c5e4a962fb07ceffb5fe6..b23b682c79c8ff61aa15d6b11011abe00c05f3c5 100644 (file)
@@ -61,8 +61,9 @@ static bool SOSDigestVectorEnsureCapacity(struct SOSDigestVector *dv, size_t cou
 
 static void SOSDigestVectorAppendOrdered(struct SOSDigestVector *dv, const uint8_t *digest)
 {
-       if (SOSDigestVectorEnsureCapacity(dv, dv->count + 1))
+    if (digest && SOSDigestVectorEnsureCapacity(dv, dv->count + 1)) {
         memcpy(dv->digest[dv->count++], digest, SOSDigestSize);
+    }
 }
 
 void SOSDigestVectorAppend(struct SOSDigestVector *dv, const uint8_t *digest)
index 672ebed2d8af855dc8606bb481198b58841bdd78..fe1b18c47f227688d7831d6221c93d7ffa37e149 100644 (file)
@@ -471,7 +471,8 @@ bool SOSEngineInitializePeerCoder(SOSEngineRef engine, SOSFullPeerInfoRef myPeer
 
     ok &= SOSEngineWithPeerID(engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *forceSaveState) {
         ok = SOSEngineEnsureCoder_locked(engine, txn, peerID, myPeerInfo, peerInfo, coder, error);
-        *forceSaveState = ok;
+        // Only set if the codersNeedSaving state gets set.
+        *forceSaveState = engine->codersNeedSaving;
     });
 
     return ok;
@@ -936,7 +937,12 @@ static void SOSEngineObjectWithView(SOSEngineRef engine, SOSObjectRef object, vo
             CFTypeRef tomb = SecDbItemGetCachedValueWithName(item, kSecAttrTombstone);
             char cvalue = 0;
             bool isTomb = (isNumber(tomb) && CFNumberGetValue(tomb, kCFNumberCharType, &cvalue) && cvalue == 1);
-            CFTypeRef viewHint = SecDbItemGetCachedValueWithName(item, kSecAttrSyncViewHint);
+            CFStringRef viewHint = SecDbItemGetCachedValueWithName(item, kSecAttrSyncViewHint);
+
+            // check that view hint is a string, if its unset it will be kCFNull
+            if (!isString(viewHint)) {
+                viewHint = NULL;
+            }
 
             // Intecept CKKS-handled items here and short-circuit function
             if(SOSViewHintInCKKSSystem(viewHint)) {
index b3aa9753eb38abe4706b11a43f563a5f37f4fc76..4e81b1c130240649fffc4d6891f582eb80d00d79 100644 (file)
@@ -183,7 +183,7 @@ static SecKeyRef ccec2SecKey(ccec_full_ctx_t fk)
 
     CFRelease(keyattributes);
     CFRelease(exportedkey);
-    bzero(export_keybytes, 0);
+    cc_clear(export_size, export_keybytes);
     return retval;
 }
 
index 165b384239bddae09b248a8ff8099fcc14c2825b..19b3cdd645f65a6c9424864c976826bf4b118c4b 100644 (file)
@@ -47,4 +47,5 @@ DOVIEWMACRO(AutoUnlock,             "AutoUnlock",           "autounlock",
 DOVIEWMACRO(Health,                 "Health",               "health",                  CKKS, D,  , A,  ,  )
 DOVIEWMACRO(ApplePay,               "ApplePay",             "applepay",                CKKS, D,  , A,  ,  )
 DOVIEWMACRO(Home,                   "Home",                 "home",                    CKKS, D,  , A,  ,  )
+DOVIEWMACRO(LimitedPeersAllowed,    "LimitedPeersAllowed",  "limitedpeersallowed",     CKKS, D,  , A,  ,  )
 
index 04a292f382f5ebbfc9c262ce445973e2abb25181..18611e4448de69de618897a3fd2ab5ba1e3eec77 100644 (file)
@@ -391,7 +391,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) {
 
 /* Verifying with attributes goes through a different code path than verifying without,
  * so we need to test both. */
-#define kNumberVerifyTests 12
+#define kNumberVerifyTests 13
 static void verify_tests(SecKeychainRef kc, bool isRsa) {
     /* no attributes */
     is(verify_please(kc, (isRsa) ? rsa_md5 : ec_md5,
@@ -418,6 +418,9 @@ static void verify_tests(SecKeychainRef kc, bool isRsa) {
     /***** Once more, with validation errors *****/
 
     /* no attributes */
+    is(verify_please(kc, (isRsa) ? rsa_sinfo_unknown_digest : ec_sinfo_unknown_digest,
+                     (isRsa) ? sizeof(rsa_sinfo_unknown_digest) : sizeof(ec_sinfo_unknown_digest)),
+       errSecInvalidDigestAlgorithm, "Verify unknown digest OID in signer info");
     is(invalidate_and_verify(kc, (isRsa) ? rsa_md5 : ec_md5,
                              (isRsa) ? sizeof(rsa_md5) : sizeof(ec_md5)),
        SECFailure, "Verify invalid MD5, no attributes");
index dc46feeb33e743212176322059a86f11b97e0af9..371b8f69bdf8d5fa2effe8371f7239003c0131b3 100644 (file)
@@ -233,6 +233,89 @@ unsigned char _ec_identity[] = {
 /*
  * MARK: RSA-signed messages (no attributes)
  */
+unsigned char rsa_sinfo_unknown_digest[] = {
+    0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
+    0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20,
+    0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41,
+    0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+    0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
+    0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53,
+    0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+    0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65,
+    0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63,
+    0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+    0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+    0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06,
+    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
+    0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34,
+    0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, 0x32,
+    0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20,
+    0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70,
+    0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53,
+    0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20,
+    0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11,
+    0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30,
+    0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
+    0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+    0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, 0xf4,
+    0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, 0xb0,
+    0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, 0xf7,
+    0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, 0xcf,
+    0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, 0x54,
+    0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, 0x00,
+    0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, 0xba,
+    0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, 0xb1,
+    0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, 0xad,
+    0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, 0x86,
+    0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, 0x6a,
+    0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, 0x0b,
+    0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, 0x52,
+    0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+    0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, 0xd5,
+    0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, 0x09,
+    0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, 0xbf,
+    0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, 0xa4,
+    0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, 0x94,
+    0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, 0x60,
+    0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, 0x61,
+    0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, 0x77,
+    0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, 0xaf,
+    0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, 0x63,
+    0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, 0x63,
+    0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, 0xa1,
+    0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, 0xca,
+    0x3f, 0xb5, 0x54, 0x31, 0x82, 0x01, 0xdb, 0x30, 0x82, 0x01, 0xd7, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, 0xa7,
+    0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+    0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49,
+    0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+    0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+    0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+    0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x02, 0x20, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+    0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x44, 0x4f, 0x1c, 0x4f, 0x73, 0x46, 0xb4, 0x67, 0x86, 0x53, 0x6e, 0x09, 0x4a, 0x18,
+    0x89, 0x82, 0xb0, 0x9d, 0xf5, 0xa9, 0x81, 0x21, 0x97, 0x2d, 0x1c, 0x61, 0x4a, 0xa0, 0x9a, 0xa1, 0x6d, 0xb0, 0xb2, 0xbe,
+    0xc8, 0x27, 0x4a, 0x0e, 0xbd, 0x52, 0xf2, 0x56, 0x8a, 0xb6, 0x41, 0x45, 0xfc, 0xf6, 0x09, 0xb7, 0x83, 0x89, 0x87, 0xc6,
+    0x5c, 0xfb, 0xe0, 0x22, 0x75, 0x9b, 0xa2, 0x24, 0x65, 0xd0, 0x51, 0xe0, 0xc6, 0x00, 0xad, 0x39, 0x50, 0x84, 0x31, 0x5c,
+    0x63, 0x54, 0x8c, 0x3c, 0xa3, 0x69, 0x7f, 0xb2, 0x2c, 0x60, 0xa1, 0x5d, 0x6a, 0xac, 0xb2, 0x02, 0x26, 0x5b, 0x82, 0x61,
+    0x2e, 0xb0, 0x32, 0xf7, 0x4e, 0xa3, 0x31, 0x00, 0xa7, 0x29, 0x4b, 0xdc, 0x30, 0x7f, 0x33, 0x14, 0x5a, 0xf1, 0x58, 0x5e,
+    0x90, 0x77, 0xf3, 0x9c, 0x68, 0xbe, 0xe9, 0x4c, 0xf6, 0x33, 0x64, 0xdf, 0x3f, 0xf4, 0xb9, 0x6b, 0xd5, 0x54, 0xb8, 0x4a,
+    0x8f, 0xbb, 0xce, 0xde, 0x4a, 0x58, 0x9e, 0xad, 0x67, 0x99, 0xbe, 0xe7, 0x0a, 0x54, 0x2b, 0x19, 0x0c, 0x45, 0x45, 0x41,
+    0x9e, 0x56, 0x07, 0x45, 0x95, 0x56, 0x92, 0xa8, 0xd6, 0x8f, 0xab, 0xb0, 0x9b, 0x39, 0xcb, 0x5a, 0x0d, 0x29, 0x2d, 0x8b,
+    0x53, 0xf4, 0x85, 0xb1, 0xec, 0x6f, 0x95, 0xd2, 0x6e, 0xd5, 0x36, 0x65, 0xd4, 0x30, 0x4d, 0x26, 0x37, 0x8b, 0x06, 0x39,
+    0xf5, 0xe6, 0xde, 0x8c, 0xf0, 0x84, 0x69, 0x96, 0xd7, 0xb9, 0x22, 0x24, 0xf5, 0x74, 0x69, 0x4e, 0x2b, 0xea, 0x9d, 0x5a,
+    0xd7, 0xfc, 0xea, 0x7d, 0x8f, 0xd7, 0x34, 0x7f, 0x4f, 0x8a, 0x5c, 0xb6, 0x73, 0x9a, 0x8f, 0xa0, 0x74, 0x5e, 0xca, 0xdc,
+    0xc9, 0x78, 0x85, 0x46, 0xb8, 0x79, 0x29, 0x10, 0xa5, 0x6c, 0x1e, 0x4e, 0xac, 0xba, 0x8e, 0xa2, 0x2d, 0xf8, 0x40, 0x2d,
+    0xde, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 unsigned char rsa_md5[] = {
     0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
     0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
@@ -750,6 +833,59 @@ unsigned char rsa_sha256_attr[] = {
 /*
  * MARK: EC-signed messages (no attributes)
  */
+unsigned char ec_sinfo_unknown_digest[] = {
+    0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
+    0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20,
+    0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41,
+    0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xa0, 0x82, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+    0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0xa6,
+    0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65,
+    0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+    0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e,
+    0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
+    0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72,
+    0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+    0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70,
+    0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, 0x39,
+    0x35, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81,
+    0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+    0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49,
+    0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+    0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+    0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+    0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, 0x88,
+    0x07, 0x03, 0x42, 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, 0x81,
+    0xa1, 0x4e, 0xc5, 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, 0x6c,
+    0xc4, 0xcd, 0x8c, 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, 0x13,
+    0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+    0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x81,
+    0x1b, 0xed, 0x5a, 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, 0x85,
+    0x7a, 0x2f, 0x65, 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, 0xcb,
+    0xeb, 0xf7, 0x1c, 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, 0xf5,
+    0xbe, 0x85, 0x40, 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x1b, 0x30, 0x82, 0x01, 0x17, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, 0x30,
+    0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20,
+    0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20,
+    0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72,
+    0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20,
+    0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+    0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61,
+    0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x02, 0x20, 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04,
+    0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xa2, 0x9f, 0x73, 0x2d, 0x2a, 0xa0, 0xca, 0xb4, 0xf6, 0xc9, 0xfd, 0x68, 0xd2, 0xe7,
+    0x8d, 0x07, 0xdd, 0x60, 0xcc, 0xe1, 0xb6, 0xfe, 0xa9, 0x11, 0xd8, 0xb7, 0x68, 0xa4, 0xe3, 0xed, 0x1b, 0x42, 0x02, 0x20,
+    0x4b, 0x64, 0x3e, 0xe0, 0x50, 0x29, 0x89, 0x30, 0xd0, 0x32, 0x2d, 0xfc, 0xd3, 0x6b, 0xe8, 0x06, 0x15, 0xe2, 0x91, 0x99,
+    0x7b, 0x26, 0xc4, 0xa3, 0x85, 0xf0, 0x05, 0x95, 0x4d, 0xf9, 0x51, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 unsigned char ec_md5[] = {
     0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01,
     0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09,
diff --git a/OSX/sec/Security/SecAccessControl.c b/OSX/sec/Security/SecAccessControl.c
deleted file mode 100644 (file)
index ed8671b..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * SecAccessControl.c - CoreFoundation based access control object
- */
-
-#include <TargetConditionals.h>
-#include <AssertMacros.h>
-#include "SecAccessControl.h"
-#include "SecAccessControlPriv.h"
-#include "SecItem.h"
-#include "SecItemPriv.h"
-#include <utilities/SecCFWrappers.h>
-#include <utilities/SecCFError.h>
-#include <utilities/der_plist.h>
-#include <libaks_acl_cf_keys.h>
-#include <ACMDefs.h>
-#include <ACMAclDefs.h>
-
-static CFTypeRef kSecAccessControlKeyProtection = CFSTR("prot");
-static CFTypeRef kSecAccessControlKeyBound = CFSTR("bound");
-
-struct __SecAccessControl {
-    CFRuntimeBase _base;
-    CFMutableDictionaryRef dict;
-};
-
-static SecAccessConstraintRef SecAccessConstraintCreateValueOfKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error);
-
-static CFStringRef SecAccessControlCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
-    SecAccessControlRef access_control = (SecAccessControlRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<SecAccessControlRef: %p>"), access_control);
-}
-
-static Boolean SecAccessControlCompare(CFTypeRef lhs, CFTypeRef rhs) {
-    SecAccessControlRef laccess_control = (SecAccessControlRef)lhs;
-    SecAccessControlRef raccess_control = (SecAccessControlRef)rhs;
-    return (laccess_control == raccess_control) || CFEqual(laccess_control->dict, raccess_control->dict);
-}
-
-static void SecAccessControlDestroy(CFTypeRef cf) {
-    SecAccessControlRef access_control = (SecAccessControlRef)cf;
-    CFReleaseSafe(access_control->dict);
-}
-
-CFGiblisWithCompareFor(SecAccessControl);
-
-static CFMutableDictionaryRef SecAccessControlGetMutableConstraints(SecAccessControlRef access_control) {
-    CFMutableDictionaryRef constraints = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
-
-    if (!constraints) {
-        CFMutableDictionaryRef newConstraints = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(access_control));
-        CFDictionarySetValue(access_control->dict, kAKSKeyAcl, newConstraints);
-        CFRelease(newConstraints);
-
-        constraints = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
-    }
-
-    return constraints;
-}
-
-SecAccessControlRef SecAccessControlCreate(CFAllocatorRef allocator, CFErrorRef *error) {
-    SecAccessControlRef access_control = CFTypeAllocate(SecAccessControl, struct __SecAccessControl, allocator);
-       if (!access_control) {
-        SecError(errSecAllocate, error, CFSTR("allocate memory for SecAccessControl"));
-        return NULL;
-    }
-
-    access_control->dict = CFDictionaryCreateMutableForCFTypes(allocator);
-    return access_control;
-}
-
-static CFDataRef _getEmptyData() {
-    static CFMutableDataRef emptyData = NULL;
-    static dispatch_once_t onceToken;
-
-    dispatch_once(&onceToken, ^{
-        emptyData = CFDataCreateMutable(kCFAllocatorDefault, 0);
-    });
-
-    return emptyData;
-}
-
-SecAccessControlRef SecAccessControlCreateWithFlags(CFAllocatorRef allocator, CFTypeRef protection,
-                                                    SecAccessControlCreateFlags flags, CFErrorRef *error) {
-    SecAccessControlRef access_control = NULL;
-    CFTypeRef constraint = NULL;
-    CFMutableArrayRef constraints = NULL;
-
-    require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut);
-
-    if (!SecAccessControlSetProtection(access_control, protection, error))
-        goto errOut;
-
-    if (flags) {
-        bool or = (flags & kSecAccessControlOr) ? true : false;
-        bool and = (flags & kSecAccessControlAnd) ? true : false;
-
-        if (or && and) {
-            SecError(errSecParam, error, CFSTR("only one logical operation can be set"));
-            goto errOut;
-        }
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunguarded-availability-new"
-
-        SecAccessControlCreateFlags maskedFlags = flags & (kSecAccessControlBiometryAny | kSecAccessControlBiometryCurrentSet);
-        if (maskedFlags && maskedFlags != kSecAccessControlBiometryAny && maskedFlags != kSecAccessControlBiometryCurrentSet) {
-            SecError(errSecParam, error, CFSTR("only one bio constraint can be set"));
-            goto errOut;
-        }
-
-        if (flags & kSecAccessControlUserPresence && flags & ~(kSecAccessControlUserPresence | kSecAccessControlApplicationPassword | kSecAccessControlPrivateKeyUsage)) {
-            SecError(errSecParam, error, CFSTR("kSecAccessControlUserPresence can be combined only with kSecAccessControlApplicationPassword and kSecAccessControlPrivateKeyUsage"));
-            goto errOut;
-        }
-
-        constraints = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
-
-        if (flags & kSecAccessControlUserPresence) {
-            require_quiet(constraint = SecAccessConstraintCreatePolicy(allocator, CFSTR(kACMPolicyDeviceOwnerAuthentication), error), errOut);
-            CFArrayAppendValue(constraints, constraint);
-            CFReleaseNull(constraint);
-        }
-
-        if (flags & kSecAccessControlDevicePasscode) {
-            require_quiet(constraint = SecAccessConstraintCreatePasscode(allocator), errOut);
-            CFArrayAppendValue(constraints, constraint);
-            CFReleaseNull(constraint);
-        }
-
-        if (flags & kSecAccessControlBiometryAny) {
-            require_quiet(constraint = SecAccessConstraintCreateBiometryAny(allocator, _getEmptyData()), errOut);
-            CFArrayAppendValue(constraints, constraint);
-            CFReleaseNull(constraint);
-        }
-
-        if (flags & kSecAccessControlBiometryCurrentSet) {
-            require_quiet(constraint = SecAccessConstraintCreateBiometryCurrentSet(allocator, _getEmptyData(), _getEmptyData()), errOut);
-            CFArrayAppendValue(constraints, constraint);
-            CFReleaseNull(constraint);
-        }
-
-#pragma clang diagnostic pop
-
-        if (flags & kSecAccessControlApplicationPassword) {
-            SecAccessControlSetRequirePassword(access_control, true);
-        }
-
-        CFIndex constraints_count = CFArrayGetCount(constraints);
-        if (constraints_count > 1) {
-            require_quiet(constraint = SecAccessConstraintCreateValueOfKofN(allocator, or?1:constraints_count, constraints, error), errOut);
-            if (flags & kSecAccessControlPrivateKeyUsage) {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, constraint, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, constraint, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
-            }
-            else {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDecrypt, constraint, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpEncrypt, kCFBooleanTrue, error), errOut);
-            }
-            require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
-            CFReleaseNull(constraint);
-        } else if (constraints_count == 1) {
-            if (flags & kSecAccessControlPrivateKeyUsage) {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
-            }
-            else {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDecrypt, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpEncrypt, kCFBooleanTrue, error), errOut);
-            }
-            require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
-        } else {
-            if (flags & kSecAccessControlPrivateKeyUsage) {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, kCFBooleanTrue, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, kCFBooleanTrue, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
-            }
-            else {
-                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDefaultAcl, kCFBooleanTrue, error), errOut);
-            }
-        }
-
-        CFReleaseNull(constraints);
-    }
-    else {
-        require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDefaultAcl, kCFBooleanTrue, error), errOut);
-    }
-
-    return access_control;
-
-errOut:
-    CFReleaseSafe(access_control);
-    CFReleaseSafe(constraints);
-    CFReleaseSafe(constraint);
-    return NULL;
-}
-
-CFTypeRef SecAccessControlGetProtection(SecAccessControlRef access_control) {
-    return CFDictionaryGetValue(access_control->dict, kSecAccessControlKeyProtection);
-}
-
-static bool checkItemInArray(CFTypeRef item, const CFTypeRef *values, CFIndex count, CFStringRef errMessage, CFErrorRef *error) {
-    for (CFIndex i = 0; i < count; i++) {
-        if (CFEqualSafe(item, values[i])) {
-            return true;
-        }
-    }
-    return SecError(errSecParam, error, CFSTR("%@: %@"), errMessage, item);
-}
-
-#define CheckItemInArray(item, values, msg) \
-{ \
-    const CFTypeRef vals[] = values; \
-    if (!checkItemInArray(item, vals, sizeof(vals)/sizeof(*vals), msg, error)) { \
-        return false; \
-    } \
-}
-
-#define ItemArray(...) { __VA_ARGS__ }
-
-
-bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef protection, CFErrorRef *error) {
-    if (!protection || CFGetTypeID(protection) != CFDictionaryGetTypeID()) {
-        // Verify protection type.
-        CheckItemInArray(protection, ItemArray(kSecAttrAccessibleAlwaysPrivate, kSecAttrAccessibleAfterFirstUnlock,
-                                               kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate,
-                                               kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
-                                               kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
-                                               kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
-                                               kSecAttrAccessibleUntilReboot),
-                         CFSTR("SecAccessControl: invalid protection"));
-    }
-
-    // Protection valid, use it.
-    CFDictionarySetValue(access_control->dict, kSecAccessControlKeyProtection, protection);
-    return true;
-}
-
-SecAccessConstraintRef SecAccessConstraintCreatePolicy(CFAllocatorRef allocator, CFTypeRef policy, CFErrorRef *error) {
-    return CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintPolicy), policy, NULL);
-}
-
-SecAccessConstraintRef SecAccessConstraintCreatePasscode(CFAllocatorRef allocator) {
-    return CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintUserPasscode), kCFBooleanTrue, NULL);
-}
-
-SecAccessConstraintRef SecAccessConstraintCreateBiometryAny(CFAllocatorRef allocator, CFDataRef catacombUUID) {
-    CFMutableDictionaryRef bioDict = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamBioCatacombUUID), catacombUUID, NULL);
-    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintBio), bioDict, NULL);
-    CFReleaseSafe(bioDict);
-    return constraint;
-}
-
-SecAccessConstraintRef SecAccessConstraintCreateTouchIDAny(CFAllocatorRef allocator, CFDataRef catacombUUID) {
-    return SecAccessConstraintCreateBiometryAny(allocator, catacombUUID);
-}
-
-SecAccessConstraintRef SecAccessConstraintCreateBiometryCurrentSet(CFAllocatorRef allocator, CFDataRef catacombUUID, CFDataRef bioDbHash) {
-    CFMutableDictionaryRef bioDict = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamBioCatacombUUID), catacombUUID, NULL);
-    CFDictionarySetValue(bioDict, CFSTR(kACMKeyAclParamBioDatabaseHash), bioDbHash);
-    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintBio), bioDict, NULL);
-    CFReleaseSafe(bioDict);
-    return constraint;
-}
-
-SecAccessConstraintRef SecAccessConstraintCreateTouchIDCurrentSet(CFAllocatorRef allocator, CFDataRef catacombUUID, CFDataRef bioDbHash) {
-    return SecAccessConstraintCreateBiometryCurrentSet(allocator, catacombUUID, bioDbHash);
-}
-
-static SecAccessConstraintRef SecAccessConstraintCreateValueOfKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error) {
-    CFNumberRef k = CFNumberCreateWithCFIndex(allocator, numRequired);
-    CFMutableDictionaryRef kofn = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamKofN), k, NULL);
-    CFRelease(k);
-
-    /* Populate kofn dictionary with constraint keys from the array. note that for now we just ignore any additional
-       constraint parameters, but we might err-out if some parameter is found, since we cannot propagate parameteres
-       into k-of-n dictionary. */
-    const CFTypeRef keysToCopy[] = { CFSTR(kACMKeyAclConstraintBio), CFSTR(kACMKeyAclConstraintPolicy),
-        CFSTR(kACMKeyAclConstraintUserPasscode) };
-    SecAccessConstraintRef constraint;
-    CFArrayForEachC(constraints, constraint) {
-        require_quiet(isDictionary(constraint), errOut);
-        bool found = false;
-        for (CFIndex i = 0; i < (CFIndex)(sizeof(keysToCopy) / sizeof(keysToCopy[0])); i++) {
-            CFTypeRef value = CFDictionaryGetValue(constraint, keysToCopy[i]);
-            if (value) {
-                CFDictionarySetValue(kofn, keysToCopy[i], value);
-                found = true;
-                break;
-            }
-        }
-        require_quiet(found, errOut);
-    }
-
-    return kofn;
-
-errOut:
-    SecError(errSecParam, error, CFSTR("SecAccessControl: invalid constraint for k-of-n"));
-    CFReleaseSafe(kofn);
-    return NULL;
-}
-
-SecAccessConstraintRef SecAccessConstraintCreateKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error) {
-    SecAccessConstraintRef valueOfKofN =  SecAccessConstraintCreateValueOfKofN(allocator, numRequired, constraints, error);
-    require_quiet(valueOfKofN, errOut);
-
-    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintKofN), valueOfKofN, NULL);
-    CFReleaseSafe(valueOfKofN);
-    return constraint;
-
-errOut:
-    return NULL;
-}
-
-bool SecAccessControlAddConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation, CFTypeRef constraint, CFErrorRef *error) {
-    CheckItemInArray(operation, ItemArray(kAKSKeyOpEncrypt, kAKSKeyOpDecrypt,
-                                          kAKSKeyOpSign, kAKSKeyOpAttest, kAKSKeyOpComputeKey,
-                                          kAKSKeyOpSync, kAKSKeyOpDefaultAcl, kAKSKeyOpDelete),
-                     CFSTR("SecAccessControl: invalid operation"));
-    if (!isDictionary(constraint) && !CFEqual(constraint, kCFBooleanTrue) && !CFEqual(constraint, kCFBooleanFalse) ) {
-        return SecError(errSecParam, error, CFSTR("invalid constraint"));
-    }
-
-    CFMutableDictionaryRef constraints = SecAccessControlGetMutableConstraints(access_control);
-    CFDictionarySetValue(constraints, operation, constraint);
-    return true;
-}
-
-SecAccessConstraintRef SecAccessControlGetConstraint(SecAccessControlRef access_control, CFTypeRef operation) {
-    CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
-    if (!ops || CFDictionaryGetCount(ops) == 0)
-        // No ACL is present, this means that everything is allowed.
-        return kCFBooleanTrue;
-
-    SecAccessConstraintRef constraint = CFDictionaryGetValue(ops, operation);
-    if (!constraint) {
-        constraint = CFDictionaryGetValue(ops, kAKSKeyOpDefaultAcl);
-    }
-    return constraint;
-}
-
-CFDataRef SecAccessControlCopyConstraintData(SecAccessControlRef access_control, CFTypeRef operation) {
-    SecAccessConstraintRef constraint = SecAccessControlGetConstraint(access_control, operation);
-
-    size_t len = der_sizeof_plist(constraint, NULL);
-    CFMutableDataRef encoded = CFDataCreateMutable(0, len);
-    CFDataSetLength(encoded, len);
-    uint8_t *der_end = CFDataGetMutableBytePtr(encoded);
-    const uint8_t *der = der_end;
-    der_end += len;
-    der_end = der_encode_plist(constraint, NULL, der, der_end);
-    if (!der_end) {
-        CFReleaseNull(encoded);
-    }
-    return encoded;
-}
-
-CFDictionaryRef SecAccessControlGetConstraints(SecAccessControlRef access_control) {
-    return CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
-}
-
-void SecAccessControlSetConstraints(SecAccessControlRef access_control, CFDictionaryRef constraints) {
-    CFMutableDictionaryRef mutableConstraints = CFDictionaryCreateMutableCopy(CFGetAllocator(access_control), 0, constraints);
-    CFDictionarySetValue(access_control->dict, kAKSKeyAcl, mutableConstraints);
-    CFReleaseSafe(mutableConstraints);
-}
-
-void SecAccessControlSetRequirePassword(SecAccessControlRef access_control, bool require) {
-    CFMutableDictionaryRef constraints = SecAccessControlGetMutableConstraints(access_control);
-    CFDictionarySetValue(constraints, kAKSKeyAclParamRequirePasscode, require?kCFBooleanTrue:kCFBooleanFalse);
-}
-
-bool SecAccessControlGetRequirePassword(SecAccessControlRef access_control) {
-    CFMutableDictionaryRef acl = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
-    if (acl) {
-        return CFEqualSafe(CFDictionaryGetValue(acl, kAKSKeyAclParamRequirePasscode), kCFBooleanTrue);
-    }
-
-    return false;
-}
-
-void SecAccessControlSetBound(SecAccessControlRef access_control, bool bound) {
-    CFDictionarySetValue(access_control->dict, kSecAccessControlKeyBound, bound ? kCFBooleanTrue : kCFBooleanFalse);
-}
-
-bool SecAccessControlIsBound(SecAccessControlRef access_control) {
-    CFTypeRef bound = CFDictionaryGetValue(access_control->dict, kSecAccessControlKeyBound);
-    return bound != NULL && CFEqualSafe(bound, kCFBooleanTrue);
-}
-
-CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control) {
-    size_t len = der_sizeof_plist(access_control->dict, NULL);
-    CFMutableDataRef encoded = CFDataCreateMutable(0, len);
-    CFDataSetLength(encoded, len);
-    uint8_t *der_end = CFDataGetMutableBytePtr(encoded);
-    const uint8_t *der = der_end;
-    der_end += len;
-    der_end = der_encode_plist(access_control->dict, NULL, der, der_end);
-    if (!der_end) {
-        CFReleaseNull(encoded);
-    }
-    return encoded;
-}
-
-SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error) {
-    SecAccessControlRef access_control;
-    require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut);
-
-    CFPropertyListRef plist;
-    const uint8_t *der = CFDataGetBytePtr(data);
-    const uint8_t *der_end = der + CFDataGetLength(data);
-    require_quiet(der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end), errOut);
-    if (der != der_end) {
-        SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data"));
-        goto errOut;
-    }
-
-    CFReleaseSafe(access_control->dict);
-    access_control->dict = (CFMutableDictionaryRef)plist;
-    return access_control;
-
-errOut:
-    CFReleaseSafe(access_control);
-    return NULL;
-}
diff --git a/OSX/sec/Security/SecAccessControl.m b/OSX/sec/Security/SecAccessControl.m
new file mode 100644 (file)
index 0000000..1f172f7
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * SecAccessControl.m - CoreFoundation based access control object
+ */
+
+#include <TargetConditionals.h>
+#include <AssertMacros.h>
+#include "SecAccessControl.h"
+#include "SecAccessControlPriv.h"
+#include "SecItem.h"
+#include "SecItemPriv.h"
+#include <utilities/SecCFWrappers.h>
+#include <utilities/SecCFError.h>
+#include <utilities/der_plist.h>
+#include <libaks_acl_cf_keys.h>
+#include <ACMDefs.h>
+#include <ACMAclDefs.h>
+
+static CFTypeRef kSecAccessControlKeyProtection = CFSTR("prot");
+static CFTypeRef kSecAccessControlKeyBound = CFSTR("bound");
+
+struct __SecAccessControl {
+    CFRuntimeBase _base;
+    CFMutableDictionaryRef dict;
+};
+
+static SecAccessConstraintRef SecAccessConstraintCreateValueOfKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error);
+
+static void dumpValue(id value, NSMutableString *target, NSString *separator) {
+    if (value == nil) {
+        // Do nothing.
+    } else if (CFGetTypeID((__bridge CFTypeRef)value) == CFBooleanGetTypeID()) {
+        [target appendString:[value boolValue] ? @"true" : @"false"];
+    } else if ([value isKindOfClass:NSNumber.class]) {
+        [target appendString:[value string]];
+    } else if ([value isKindOfClass:NSString.class]) {
+        [target appendString:value];
+    } else if ([value isKindOfClass:NSDictionary.class]) {
+        [value enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
+            [target appendString:separator];
+            dumpValue(key, target, @"");
+            [target appendString:@"("];
+            dumpValue(obj, target, @"");
+            [target appendString:@")"];
+        }];
+    }
+}
+
+static CFStringRef SecAccessControlCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
+    SecAccessControlRef access_control = (SecAccessControlRef)cf;
+    NSDictionary *contents = (__bridge NSDictionary *)access_control->dict;
+    NSMutableString *dump = [NSMutableString string];
+    dumpValue(contents[(__bridge id)kSecAccessControlKeyProtection], dump, @"");
+    dumpValue(contents[(__bridge id)kAKSKeyAcl], dump, @";");
+    return CFBridgingRetain([NSString stringWithFormat:@"<SecAccessControlRef: %@>", dump]);
+}
+
+static Boolean SecAccessControlCompare(CFTypeRef lhs, CFTypeRef rhs) {
+    SecAccessControlRef laccess_control = (SecAccessControlRef)lhs;
+    SecAccessControlRef raccess_control = (SecAccessControlRef)rhs;
+    return (laccess_control == raccess_control) || CFEqual(laccess_control->dict, raccess_control->dict);
+}
+
+static void SecAccessControlDestroy(CFTypeRef cf) {
+    SecAccessControlRef access_control = (SecAccessControlRef)cf;
+    CFReleaseSafe(access_control->dict);
+}
+
+CFGiblisWithCompareFor(SecAccessControl);
+
+static CFMutableDictionaryRef SecAccessControlGetMutableConstraints(SecAccessControlRef access_control) {
+    CFMutableDictionaryRef constraints = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
+
+    if (!constraints) {
+        CFMutableDictionaryRef newConstraints = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(access_control));
+        CFDictionarySetValue(access_control->dict, kAKSKeyAcl, newConstraints);
+        CFRelease(newConstraints);
+
+        constraints = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
+    }
+
+    return constraints;
+}
+
+SecAccessControlRef SecAccessControlCreate(CFAllocatorRef allocator, CFErrorRef *error) {
+    SecAccessControlRef access_control = CFTypeAllocate(SecAccessControl, struct __SecAccessControl, allocator);
+       if (!access_control) {
+        SecError(errSecAllocate, error, CFSTR("allocate memory for SecAccessControl"));
+        return NULL;
+    }
+
+    access_control->dict = CFDictionaryCreateMutableForCFTypes(allocator);
+    return access_control;
+}
+
+static CFDataRef _getEmptyData() {
+    static CFMutableDataRef emptyData = NULL;
+    static dispatch_once_t onceToken;
+
+    dispatch_once(&onceToken, ^{
+        emptyData = CFDataCreateMutable(kCFAllocatorDefault, 0);
+    });
+
+    return emptyData;
+}
+
+SecAccessControlRef SecAccessControlCreateWithFlags(CFAllocatorRef allocator, CFTypeRef protection,
+                                                    SecAccessControlCreateFlags flags, CFErrorRef *error) {
+    SecAccessControlRef access_control = NULL;
+    CFTypeRef constraint = NULL;
+    CFMutableArrayRef constraints = NULL;
+
+    require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut);
+
+    if (!SecAccessControlSetProtection(access_control, protection, error))
+        goto errOut;
+
+    if (flags) {
+        bool or = (flags & kSecAccessControlOr) ? true : false;
+        bool and = (flags & kSecAccessControlAnd) ? true : false;
+
+        if (or && and) {
+            SecError(errSecParam, error, CFSTR("only one logical operation can be set"));
+            goto errOut;
+        }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
+        SecAccessControlCreateFlags maskedFlags = flags & (kSecAccessControlBiometryAny | kSecAccessControlBiometryCurrentSet);
+        if (maskedFlags && maskedFlags != kSecAccessControlBiometryAny && maskedFlags != kSecAccessControlBiometryCurrentSet) {
+            SecError(errSecParam, error, CFSTR("only one bio constraint can be set"));
+            goto errOut;
+        }
+
+        if (flags & kSecAccessControlUserPresence && flags & ~(kSecAccessControlUserPresence | kSecAccessControlApplicationPassword | kSecAccessControlPrivateKeyUsage)) {
+            SecError(errSecParam, error, CFSTR("kSecAccessControlUserPresence can be combined only with kSecAccessControlApplicationPassword and kSecAccessControlPrivateKeyUsage"));
+            goto errOut;
+        }
+
+        constraints = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
+
+        if (flags & kSecAccessControlUserPresence) {
+            require_quiet(constraint = SecAccessConstraintCreatePolicy(allocator, CFSTR(kACMPolicyDeviceOwnerAuthentication), error), errOut);
+            CFArrayAppendValue(constraints, constraint);
+            CFReleaseNull(constraint);
+        }
+
+        if (flags & kSecAccessControlDevicePasscode) {
+            require_quiet(constraint = SecAccessConstraintCreatePasscode(allocator), errOut);
+            CFArrayAppendValue(constraints, constraint);
+            CFReleaseNull(constraint);
+        }
+
+        if (flags & kSecAccessControlBiometryAny) {
+            require_quiet(constraint = SecAccessConstraintCreateBiometryAny(allocator, _getEmptyData()), errOut);
+            CFArrayAppendValue(constraints, constraint);
+            CFReleaseNull(constraint);
+        }
+
+        if (flags & kSecAccessControlBiometryCurrentSet) {
+            require_quiet(constraint = SecAccessConstraintCreateBiometryCurrentSet(allocator, _getEmptyData(), _getEmptyData()), errOut);
+            CFArrayAppendValue(constraints, constraint);
+            CFReleaseNull(constraint);
+        }
+
+#pragma clang diagnostic pop
+
+        if (flags & kSecAccessControlApplicationPassword) {
+            SecAccessControlSetRequirePassword(access_control, true);
+        }
+
+        CFIndex constraints_count = CFArrayGetCount(constraints);
+        if (constraints_count > 1) {
+            require_quiet(constraint = SecAccessConstraintCreateValueOfKofN(allocator, or?1:constraints_count, constraints, error), errOut);
+            if (flags & kSecAccessControlPrivateKeyUsage) {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, constraint, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, constraint, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
+            }
+            else {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDecrypt, constraint, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpEncrypt, kCFBooleanTrue, error), errOut);
+            }
+            require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
+            CFReleaseNull(constraint);
+        } else if (constraints_count == 1) {
+            if (flags & kSecAccessControlPrivateKeyUsage) {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
+            }
+            else {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDecrypt, CFArrayGetValueAtIndex(constraints, 0), error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpEncrypt, kCFBooleanTrue, error), errOut);
+            }
+            require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
+        } else {
+            if (flags & kSecAccessControlPrivateKeyUsage) {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpSign, kCFBooleanTrue, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpComputeKey, kCFBooleanTrue, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpAttest, kCFBooleanTrue, error), errOut);
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut);
+            }
+            else {
+                require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDefaultAcl, kCFBooleanTrue, error), errOut);
+            }
+        }
+
+        CFReleaseNull(constraints);
+    }
+    else {
+        require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDefaultAcl, kCFBooleanTrue, error), errOut);
+    }
+
+    return access_control;
+
+errOut:
+    CFReleaseSafe(access_control);
+    CFReleaseSafe(constraints);
+    CFReleaseSafe(constraint);
+    return NULL;
+}
+
+CFTypeRef SecAccessControlGetProtection(SecAccessControlRef access_control) {
+    return CFDictionaryGetValue(access_control->dict, kSecAccessControlKeyProtection);
+}
+
+static bool checkItemInArray(CFTypeRef item, const CFTypeRef *values, CFIndex count, CFStringRef errMessage, CFErrorRef *error) {
+    for (CFIndex i = 0; i < count; i++) {
+        if (CFEqualSafe(item, values[i])) {
+            return true;
+        }
+    }
+    return SecError(errSecParam, error, CFSTR("%@: %@"), errMessage, item);
+}
+
+#define CheckItemInArray(item, values, msg) \
+{ \
+    const CFTypeRef vals[] = values; \
+    if (!checkItemInArray(item, vals, sizeof(vals)/sizeof(*vals), msg, error)) { \
+        return false; \
+    } \
+}
+
+#define ItemArray(...) { __VA_ARGS__ }
+
+
+bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef protection, CFErrorRef *error) {
+    if (!protection || CFGetTypeID(protection) != CFDictionaryGetTypeID()) {
+        // Verify protection type.
+        CheckItemInArray(protection, ItemArray(kSecAttrAccessibleAlwaysPrivate, kSecAttrAccessibleAfterFirstUnlock,
+                                               kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate,
+                                               kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
+                                               kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
+                                               kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
+                                               kSecAttrAccessibleUntilReboot),
+                         CFSTR("SecAccessControl: invalid protection"));
+    }
+
+    // Protection valid, use it.
+    CFDictionarySetValue(access_control->dict, kSecAccessControlKeyProtection, protection);
+    return true;
+}
+
+SecAccessConstraintRef SecAccessConstraintCreatePolicy(CFAllocatorRef allocator, CFTypeRef policy, CFErrorRef *error) {
+    return CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintPolicy), policy, NULL);
+}
+
+SecAccessConstraintRef SecAccessConstraintCreatePasscode(CFAllocatorRef allocator) {
+    return CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintUserPasscode), kCFBooleanTrue, NULL);
+}
+
+SecAccessConstraintRef SecAccessConstraintCreateBiometryAny(CFAllocatorRef allocator, CFDataRef catacombUUID) {
+    CFMutableDictionaryRef bioDict = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamBioCatacombUUID), catacombUUID, NULL);
+    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintBio), bioDict, NULL);
+    CFReleaseSafe(bioDict);
+    return constraint;
+}
+
+SecAccessConstraintRef SecAccessConstraintCreateTouchIDAny(CFAllocatorRef allocator, CFDataRef catacombUUID) {
+    return SecAccessConstraintCreateBiometryAny(allocator, catacombUUID);
+}
+
+SecAccessConstraintRef SecAccessConstraintCreateBiometryCurrentSet(CFAllocatorRef allocator, CFDataRef catacombUUID, CFDataRef bioDbHash) {
+    CFMutableDictionaryRef bioDict = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamBioCatacombUUID), catacombUUID, NULL);
+    CFDictionarySetValue(bioDict, CFSTR(kACMKeyAclParamBioDatabaseHash), bioDbHash);
+    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintBio), bioDict, NULL);
+    CFReleaseSafe(bioDict);
+    return constraint;
+}
+
+SecAccessConstraintRef SecAccessConstraintCreateTouchIDCurrentSet(CFAllocatorRef allocator, CFDataRef catacombUUID, CFDataRef bioDbHash) {
+    return SecAccessConstraintCreateBiometryCurrentSet(allocator, catacombUUID, bioDbHash);
+}
+
+static SecAccessConstraintRef SecAccessConstraintCreateValueOfKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error) {
+    CFNumberRef k = CFNumberCreateWithCFIndex(allocator, numRequired);
+    CFMutableDictionaryRef kofn = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclParamKofN), k, NULL);
+    CFRelease(k);
+
+    /* Populate kofn dictionary with constraint keys from the array. note that for now we just ignore any additional
+       constraint parameters, but we might err-out if some parameter is found, since we cannot propagate parameteres
+       into k-of-n dictionary. */
+    const CFTypeRef keysToCopy[] = { CFSTR(kACMKeyAclConstraintBio), CFSTR(kACMKeyAclConstraintPolicy),
+        CFSTR(kACMKeyAclConstraintUserPasscode) };
+    SecAccessConstraintRef constraint;
+    CFArrayForEachC(constraints, constraint) {
+        require_quiet(isDictionary(constraint), errOut);
+        bool found = false;
+        for (CFIndex i = 0; i < (CFIndex)(sizeof(keysToCopy) / sizeof(keysToCopy[0])); i++) {
+            CFTypeRef value = CFDictionaryGetValue(constraint, keysToCopy[i]);
+            if (value) {
+                CFDictionarySetValue(kofn, keysToCopy[i], value);
+                found = true;
+                break;
+            }
+        }
+        require_quiet(found, errOut);
+    }
+
+    return kofn;
+
+errOut:
+    SecError(errSecParam, error, CFSTR("SecAccessControl: invalid constraint for k-of-n"));
+    CFReleaseSafe(kofn);
+    return NULL;
+}
+
+SecAccessConstraintRef SecAccessConstraintCreateKofN(CFAllocatorRef allocator, size_t numRequired, CFArrayRef constraints, CFErrorRef *error) {
+    SecAccessConstraintRef valueOfKofN =  SecAccessConstraintCreateValueOfKofN(allocator, numRequired, constraints, error);
+    require_quiet(valueOfKofN, errOut);
+
+    SecAccessConstraintRef constraint = CFDictionaryCreateMutableForCFTypesWith(allocator, CFSTR(kACMKeyAclConstraintKofN), valueOfKofN, NULL);
+    CFReleaseSafe(valueOfKofN);
+    return constraint;
+
+errOut:
+    return NULL;
+}
+
+bool SecAccessControlAddConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation, CFTypeRef constraint, CFErrorRef *error) {
+    if (!isDictionary(constraint) && !CFEqual(constraint, kCFBooleanTrue) && !CFEqual(constraint, kCFBooleanFalse) ) {
+        return SecError(errSecParam, error, CFSTR("invalid constraint"));
+    }
+
+    CFMutableDictionaryRef constraints = SecAccessControlGetMutableConstraints(access_control);
+    CFDictionarySetValue(constraints, operation, constraint);
+    return true;
+}
+
+SecAccessConstraintRef SecAccessControlGetConstraint(SecAccessControlRef access_control, CFTypeRef operation) {
+    CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
+    if (!ops || CFDictionaryGetCount(ops) == 0)
+        // No ACL is present, this means that everything is allowed.
+        return kCFBooleanTrue;
+
+    SecAccessConstraintRef constraint = CFDictionaryGetValue(ops, operation);
+    if (!constraint) {
+        constraint = CFDictionaryGetValue(ops, kAKSKeyOpDefaultAcl);
+    }
+    return constraint;
+}
+
+CFDataRef SecAccessControlCopyConstraintData(SecAccessControlRef access_control, CFTypeRef operation) {
+    SecAccessConstraintRef constraint = SecAccessControlGetConstraint(access_control, operation);
+
+    size_t len = der_sizeof_plist(constraint, NULL);
+    CFMutableDataRef encoded = CFDataCreateMutable(0, len);
+    CFDataSetLength(encoded, len);
+    uint8_t *der_end = CFDataGetMutableBytePtr(encoded);
+    const uint8_t *der = der_end;
+    der_end += len;
+    der_end = der_encode_plist(constraint, NULL, der, der_end);
+    if (!der_end) {
+        CFReleaseNull(encoded);
+    }
+    return encoded;
+}
+
+CFDictionaryRef SecAccessControlGetConstraints(SecAccessControlRef access_control) {
+    return CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
+}
+
+void SecAccessControlSetConstraints(SecAccessControlRef access_control, CFDictionaryRef constraints) {
+    CFMutableDictionaryRef mutableConstraints = CFDictionaryCreateMutableCopy(CFGetAllocator(access_control), 0, constraints);
+    CFDictionarySetValue(access_control->dict, kAKSKeyAcl, mutableConstraints);
+    CFReleaseSafe(mutableConstraints);
+}
+
+void SecAccessControlSetRequirePassword(SecAccessControlRef access_control, bool require) {
+    CFMutableDictionaryRef constraints = SecAccessControlGetMutableConstraints(access_control);
+    CFDictionarySetValue(constraints, kAKSKeyAclParamRequirePasscode, require?kCFBooleanTrue:kCFBooleanFalse);
+}
+
+bool SecAccessControlGetRequirePassword(SecAccessControlRef access_control) {
+    CFMutableDictionaryRef acl = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl);
+    if (acl) {
+        return CFEqualSafe(CFDictionaryGetValue(acl, kAKSKeyAclParamRequirePasscode), kCFBooleanTrue);
+    }
+
+    return false;
+}
+
+void SecAccessControlSetBound(SecAccessControlRef access_control, bool bound) {
+    CFDictionarySetValue(access_control->dict, kSecAccessControlKeyBound, bound ? kCFBooleanTrue : kCFBooleanFalse);
+}
+
+bool SecAccessControlIsBound(SecAccessControlRef access_control) {
+    CFTypeRef bound = CFDictionaryGetValue(access_control->dict, kSecAccessControlKeyBound);
+    return bound != NULL && CFEqualSafe(bound, kCFBooleanTrue);
+}
+
+CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control) {
+    size_t len = der_sizeof_plist(access_control->dict, NULL);
+    CFMutableDataRef encoded = CFDataCreateMutable(0, len);
+    CFDataSetLength(encoded, len);
+    uint8_t *der_end = CFDataGetMutableBytePtr(encoded);
+    const uint8_t *der = der_end;
+    der_end += len;
+    der_end = der_encode_plist(access_control->dict, NULL, der, der_end);
+    if (!der_end) {
+        CFReleaseNull(encoded);
+    }
+    return encoded;
+}
+
+SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error) {
+    SecAccessControlRef access_control;
+    require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut);
+
+    CFPropertyListRef plist;
+    const uint8_t *der = CFDataGetBytePtr(data);
+    const uint8_t *der_end = der + CFDataGetLength(data);
+    require_quiet(der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end), errOut);
+    if (der != der_end) {
+        SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data"));
+        goto errOut;
+    }
+
+    CFReleaseSafe(access_control->dict);
+    access_control->dict = (CFMutableDictionaryRef)plist;
+    return access_control;
+
+errOut:
+    CFReleaseSafe(access_control);
+    return NULL;
+}
index fc35e4ccc481b101a6a7468344570a03a4df3661..44e1dd81bfc6116366b37c9a4d4ff428b7516acd 100644 (file)
@@ -73,7 +73,8 @@ static CFIndex SecCTKGetAlgorithmID(SecKeyRef key) {
 
 static SecItemAuthResult SecCTKProcessError(CFStringRef operation, TKTokenRef token, CFDataRef object_id, CFArrayRef *ac_pairs, CFErrorRef *error) {
     if (CFEqualSafe(CFErrorGetDomain(*error), CFSTR(kTKErrorDomain)) &&
-        CFErrorGetCode(*error) == kTKErrorCodeAuthenticationFailed) {
+        CFErrorGetCode(*error) == kTKErrorCodeAuthenticationFailed &&
+        operation != NULL) {
         CFDataRef access_control = TKTokenCopyObjectAccessControl(token, object_id, error);
         if (access_control != NULL) {
             CFArrayRef ac_pair = CFArrayCreateForCFTypes(NULL, access_control, operation, NULL);
@@ -88,12 +89,6 @@ static SecItemAuthResult SecCTKProcessError(CFStringRef operation, TKTokenRef to
     return kSecItemAuthResultError;
 }
 
-static const CFTypeRef *aclOperations[] = {
-    [kSecKeyOperationTypeSign] = &kAKSKeyOpSign,
-    [kSecKeyOperationTypeDecrypt] = &kAKSKeyOpDecrypt,
-    [kSecKeyOperationTypeKeyExchange] = &kAKSKeyOpComputeKey,
-};
-
 static TKTokenRef SecCTKKeyCreateToken(SecKeyRef key, CFDictionaryRef auth_params, CFDictionaryRef *last_params, CFErrorRef *error) {
     TKTokenRef token = NULL;
     SecCTKKeyData *kd = key->key;
@@ -161,8 +156,31 @@ static CFTypeRef SecCTKKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType
         if (CFEqualSafe(result, kCFBooleanTrue)) {
             result = TKTokenCopyOperationResult(token, kd->object_id, operation, algorithms, mode, in1, in2, error);
         }
-        return (result != NULL) ? kSecItemAuthResultOK : SecCTKProcessError(*aclOperations[operation], token,
-                                                                            kd->object_id, ac_pairs, error);
+
+        if (result != NULL) {
+            return kSecItemAuthResultOK;
+        }
+
+        CFStringRef AKSOperation = NULL;
+        switch (operation) {
+            case kSecKeyOperationTypeSign:
+                AKSOperation = kAKSKeyOpSign;
+                break;
+            case kSecKeyOperationTypeDecrypt: {
+                AKSOperation = kAKSKeyOpDecrypt;
+                if (in2 != NULL && CFGetTypeID(in2) == CFDictionaryGetTypeID() && CFDictionaryGetValue(in2, kSecKeyEncryptionParameterRecryptCertificate) != NULL) {
+                    // This is actually recrypt operation, which is special separate AKS operation.
+                    AKSOperation = kAKSKeyOpECIESTranscode;
+                }
+                break;
+            }
+            case kSecKeyOperationTypeKeyExchange:
+                AKSOperation = kAKSKeyOpComputeKey;
+                break;
+            default:
+                break;;
+        }
+        return SecCTKProcessError(AKSOperation, token, kd->object_id, ac_pairs, error);
     }, ^{
         CFAssignRetained(token, SecCTKKeyCreateToken(key, auth_params.dictionary, &last_params, NULL));
     });
@@ -570,11 +588,6 @@ out:
     return attestationData;
 }
 
-#if TKTOKEN_CLIENT_INTERFACE_VERSION < 4
-#define kTKTokenControlAttribLifetimeControlKey "lifetimeControlKey"
-#define kTKTokenControlAttribLifetimeType "lifetimeType"
-#endif
-
 Boolean SecKeyControlLifetime(SecKeyRef key, SecKeyControlLifetimeType type, CFErrorRef *error) {
     NSError *localError;
     __block id token;
@@ -605,3 +618,19 @@ Boolean SecKeyControlLifetime(SecKeyRef key, SecKeyControlLifetimeType type, CFE
         return outputAttributes ? kSecItemAuthResultOK : kSecItemAuthResultError;
     }, NULL);
 }
+
+#if TKTOKEN_CLIENT_INTERFACE_VERSION < 5
+#define kTKTokenCreateAttributeTestMode "testmode"
+#endif
+
+void SecCTKKeySetTestMode(CFStringRef tokenID, CFTypeRef enable) {
+    CFErrorRef error = NULL;
+    CFDictionaryRef options = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrTokenID, tokenID, @kTKTokenCreateAttributeTestMode, enable, nil);
+    TKTokenRef token = TKTokenCreate(options, &error);
+    if (token == NULL) {
+        secerror("Failed to set token attributes %@: error %@", options, error);
+    }
+    CFReleaseNull(options);
+    CFReleaseNull(error);
+    CFReleaseNull(token);
+}
index 660a008047752b41278961d81dedbc85485719a9..be40b1789774d525d9c0eafa2d34eaa88ad18ec6 100644 (file)
@@ -34,6 +34,7 @@ extern const CFStringRef kSecUseToken;
 OSStatus SecCTKKeyGeneratePair(CFDictionaryRef parameters,
                                SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey);
 SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttributes, CFErrorRef *error);
+void SecCTKKeySetTestMode(CFStringRef tokenID, CFTypeRef enable);
 
 __END_DECLS
 
index 8f243e706c653dc752e38f224517ab9dda698f4b..2c5d15377185cef5c9c0ea1fa15af530db9eeeff 100644 (file)
@@ -1078,10 +1078,12 @@ _SecKeyCopyPublicKeyHash
 _SecKeyCreate
 _SecKeyCreateAttestation
 _SecKeyCreateDecryptedData
+_SecKeyCreateDecryptedDataWithParameters
 _SecKeyCreateDuplicate
 _SecKeyCreateECPrivateKey
 _SecKeyCreateECPublicKey
 _SecKeyCreateEncryptedData
+_SecKeyCreateEncryptedDataWithParameters
 _SecKeyCreateFromAttributeDictionary
 
 #if TARGET_OS_OSX
@@ -1248,9 +1250,14 @@ _kSecKeyAlgorithmRSASignatureRawCCUnit
 #if TARGET_OS_OSX
 _kSecKeyAttributeName
 #endif /* TARGET_OS_OSX */
+_kSecKeyEncryptionParameterRecryptParameters
+_kSecKeyEncryptionParameterRecryptCertificate
+_kSecKeyEncryptionParameterSymmetricAAD
+_kSecKeyEncryptionParameterSymmetricKeySizeInBits
 _kSecKeyKeyExchangeParameterRequestedSize
 _kSecKeyKeyExchangeParameterSharedInfo
 _kSecKeyParameterSETokenAttestationNonce
+_kSecKeyApplePayEnabled
 _kSecPrivateKeyAttrs
 _kSecPublicKeyAttrs
 
index 10943094c74e2de66479bf10b5de231e7c79f4dd..5f86dd330e1a1f9035f8cc6d8c1fb564bb95b934 100644 (file)
@@ -291,7 +291,7 @@ __BEGIN_DECLS
 #define SEC_TRUST_ERROR_IntermediateEKU             SecStringWithDefaultValue("Extended key usage does not match pinned value", "Trust", 0, "Extended key usage does not match pinned value", "Error for intermediate extended key usage pin")
 #define SEC_TRUST_ERROR_IntermediateMarkerOid       SecStringWithDefaultValue("Missing issuer-specific extension OID", "Trust", 0, "Missing issuer-specific extension OID", "Error for intermediate marker OID")
 #define SEC_TRUST_ERROR_IntermediateOrganization    SecStringWithDefaultValue("Organization does not match expected name", "Trust", 0, "Organization does not match expected name", "Error for issuer organization mismatch")
-#define SEC_TRUST_ERROR_IntermediateCountry         SecStringWithDefaultValue("Country does not match expected name", "Trust", 0, "Country does not match expected name", "Error for issuer country mismatch")
+#define SEC_TRUST_ERROR_IntermediateCountry         SecStringWithDefaultValue("Country or Region does not match expected name", "Trust", 0, "Country or Region does not match expected name", "Error for issuer country mismatch")
 #define SEC_TRUST_ERROR_AnchorSHA1                  SecStringWithDefaultValue("Anchor does not match pinned fingerprint", "Trust", 0, "Anchor does not match pinned fingerprint", "Error for anchor SHA-1 fingerprint pin")
 #define SEC_TRUST_ERROR_AnchorSHA256                SecStringWithDefaultValue("Anchor does not match pinned fingerprint", "Trust", 0, "Anchor does not match pinned fingerprint", "Error for anchor SHA-256 fingerprint pin")
 #define SEC_TRUST_ERROR_AnchorTrusted               SecStringWithDefaultValue("Root is not trusted", "Trust", 0, "Root is not trusted", "Error for untrusted root")
index 6d3b595c0ae8176f9cbb447c551ac5afa56fed9e..a5028e0d0788f2bba9e1846e6af16af835f06261 100644 (file)
@@ -828,6 +828,7 @@ TKTokenRef SecTokenCreate(CFStringRef token_id, SecCFDictionaryCOW *auth_params,
         if (ctx == nil) {
             ctx = LACreateNewContextWithACMContext(NULL, error);
             if (!ctx) {
+                os_unfair_lock_unlock(&lock);
                 secerror("Failed to create authentication context %@", *error);
                 return token;
             }
@@ -1542,9 +1543,7 @@ static bool SecTokenProcessError(CFStringRef operation, TKTokenRef token, CFType
         // Replace error with the one which is augmented with access control and operation which failed,
         // which will cause SecItemDoWithAuth to throw UI.
         // Create array containing tuple (array) with error and requested operation.
-        CFDataRef access_control = (CFGetTypeID(object_or_attrs) == CFDataGetTypeID()) ?
-            TKTokenCopyObjectAccessControl(token, object_or_attrs, error) :
-            TKTokenCopyObjectCreationAccessControl(token, object_or_attrs, error);
+        CFDataRef access_control = TKTokenCopyObjectAccessControl(token, object_or_attrs, error);
         if (access_control != NULL) {
             SecTokenCreateAccessControlError(operation, access_control, error);
             CFRelease(access_control);
index 3231cbc307bd25ad1400f0ea8daa06f1e5862aca..929a66a55a03a9f5adbb2d24cd863d029fe45c42 100644 (file)
@@ -242,6 +242,7 @@ SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna");
    any SecItem apis directly. */
 SEC_CONST_DECL (kSecPrivateKeyAttrs, "private");
 SEC_CONST_DECL (kSecPublicKeyAttrs, "public");
+SEC_CONST_DECL (kSecKeyApplePayEnabled, "applepay");
 
 /* This is here only temporarily until MobileActivation starts using kSecAttrTokenOID instead of this specific attribute. */
 SEC_CONST_DECL (kSecAttrSecureEnclaveKeyBlob, "toid");
index 3a49b7c498e7c107b4873f66330530674844637e..545900fae8b312d53f9fd8ea2784285a676efad8 100644 (file)
@@ -31,6 +31,7 @@
 #include <Security/SecItemPriv.h>
 #include <Security/SecItemShim.h>
 #include <Security/SecFramework.h>
+#include <Security/SecCertificate.h>
 
 #include <utilities/SecIOFormat.h>
 
@@ -1376,7 +1377,10 @@ SecKeyRef SecKeyCreateDuplicate(SecKeyRef key) {
 }
 
 Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) {
-    if (key->key_class->version >= 4 && key->key_class->setParameter) {
+    if (key == NULL) {
+        SecCTKKeySetTestMode(name, value);
+        return true;
+    } else if (key->key_class->version >= 4 && key->key_class->setParameter) {
         CFErrorRef localError = NULL;
         Boolean result = key->key_class->setParameter(key, name, value, &localError);
         SecKeyErrorPropagate(result, localError, error);
@@ -1560,22 +1564,32 @@ Boolean SecKeyVerifySignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRe
     return result;
 }
 
-CFDataRef SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plainText, CFErrorRef *error) {
+CFDataRef SecKeyCreateEncryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext,
+                                                  CFDictionaryRef parameters, CFErrorRef *error) {
     CFErrorRef localError = NULL;
     SecKeyOperationContext context = { key, kSecKeyOperationTypeEncrypt, SecKeyCreateAlgorithmArray(algorithm) };
-    CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, plainText, NULL, &localError);
+    CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, plaintext, parameters, &localError);
     SecKeyOperationContextDestroy(&context);
     SecKeyErrorPropagate(result, localError, error);
     return result;
 }
 
-CFDataRef SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef cipherText, CFErrorRef *error) {
+CFDataRef SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext, CFErrorRef *error) {
+    return SecKeyCreateEncryptedDataWithParameters(key, algorithm, plaintext, NULL, error);
+}
+
+CFDataRef SecKeyCreateDecryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext,
+                                                  CFDictionaryRef parameters, CFErrorRef *error) {
     SecKeyOperationContext context = { key, kSecKeyOperationTypeDecrypt, SecKeyCreateAlgorithmArray(algorithm) };
-    CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, cipherText, NULL, error);
+    CFDataRef result = SecKeyRunAlgorithmAndCopyResult(&context, ciphertext, parameters, error);
     SecKeyOperationContextDestroy(&context);
     return result;
 }
 
+CFDataRef SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext, CFErrorRef *error) {
+    return SecKeyCreateDecryptedDataWithParameters(key, algorithm, ciphertext, NULL, error);
+}
+
 CFDataRef SecKeyCopyKeyExchangeResult(SecKeyRef key, SecKeyAlgorithm algorithm, SecKeyRef publicKey,
                                       CFDictionaryRef parameters, CFErrorRef *error) {
     CFErrorRef localError = NULL;
index 4c36959159f66986004f10684c3c0dbebbfd975d..d2bfc63799a41294d777ee9621ba76b5bdb04ea1 100644 (file)
@@ -583,6 +583,11 @@ RSA_OAEP_CRYPT_ADAPTOR(SHA512, ccsha512_di());
 const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterRequestedSize = CFSTR("requestedSize");
 const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterSharedInfo = CFSTR("sharedInfo");
 
+const CFStringRef kSecKeyEncryptionParameterSymmetricKeySizeInBits = CFSTR("symKeySize");
+const CFStringRef kSecKeyEncryptionParameterSymmetricAAD = CFSTR("aad");
+const CFStringRef kSecKeyEncryptionParameterRecryptParameters = CFSTR("recryptParams");
+const CFStringRef kSecKeyEncryptionParameterRecryptCertificate = CFSTR("recryptCert");
+
 static CFTypeRef SecKeyECDHCopyX963Result(SecKeyOperationContext *context, const struct ccdigest_info *di,
                                           CFTypeRef in1, CFTypeRef params, CFErrorRef *error) {
     CFTypeRef result = NULL;
@@ -648,9 +653,9 @@ static CFIndex SecKeyGetCFIndexFromRef(CFTypeRef ref) {
     return result;
 }
 
-typedef CFDataRef (*SecKeyECIESKeyExchangeCopyResult)(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm, bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey, bool variableIV, CFErrorRef *error);
-typedef Boolean (*SecKeyECIESEncryptCopyResult)(CFDataRef keyExchangeResult, CFDataRef inData, CFMutableDataRef result, CFErrorRef *error);
-typedef CFDataRef SecKeyECIESDecryptCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error);
+typedef CFDataRef (*SecKeyECIESKeyExchangeCopyResult)(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm, bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey, bool variableIV, CFDictionaryRef inParams, CFErrorRef *error);
+typedef Boolean (*SecKeyECIESEncryptCopyResult)(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams, CFMutableDataRef result, CFErrorRef *error);
+typedef CFDataRef SecKeyECIESDecryptCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams, CFErrorRef *error);
 
 static CFTypeRef SecKeyECIESCopyEncryptedData(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
                                               SecKeyECIESKeyExchangeCopyResult keyExchangeCopyResult,
@@ -681,11 +686,11 @@ static CFTypeRef SecKeyECIESCopyEncryptedData(SecKeyOperationContext *context, S
 
     context->key = ephemeralPrivateKey;
     require_quiet(keyExchangeResult = keyExchangeCopyResult(context, keyExchangeAlgorithm, true,
-                                                            ephemeralPubKeyData, pubKeyData, variableIV, error), out);
+                                                            ephemeralPubKeyData, pubKeyData, variableIV, in2, error), out);
     if (context->mode == kSecKeyOperationModePerform) {
         // Encrypt input data using AES-GCM.
         ciphertext = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, ephemeralPubKeyData);
-        require_quiet(encryptCopyResult(keyExchangeResult, in1, ciphertext, error), out);
+        require_quiet(encryptCopyResult(keyExchangeResult, in1, in2, ciphertext, error), out);
         result = CFRetain(ciphertext);
     } else {
         result = CFRetain(keyExchangeResult);
@@ -736,12 +741,12 @@ static CFTypeRef SecKeyECIESCopyDecryptedData(SecKeyOperationContext *context, S
 
     // Perform keyExchange operation.
     require_quiet(keyExchangeResult = keyExchangeCopyResult(context, keyExchangeAlgorithm, false,
-                                                            ephemeralPubKeyData, pubKeyData, variableIV, error), out);
+                                                            ephemeralPubKeyData, pubKeyData, variableIV, in2, error), out);
     if (context->mode == kSecKeyOperationModePerform) {
         // Decrypt ciphertext using AES-GCM.
         ciphertext = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ciphertextBuffer, CFDataGetLength(in1) - (keySize * 2 + 1),
                                                  kCFAllocatorNull);
-        require_quiet(result = decryptCopyResult(keyExchangeResult, ciphertext, error), out);
+        require_quiet(result = decryptCopyResult(keyExchangeResult, ciphertext, in2, error), out);
     } else {
         result = CFRetain(keyExchangeResult);
     }
@@ -761,45 +766,55 @@ static const UInt8 kSecKeyIESIV[16] = { 0 };
 
 static CFDataRef SecKeyECIESKeyExchangeKDFX963CopyResult(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
                                                          bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey, bool variableIV,
-                                                         CFErrorRef *error) {
-    CFDictionaryRef parameters = NULL;
-    CFNumberRef keySizeRef = NULL;
-    CFDataRef result = NULL;
+                                                         CFDictionaryRef inParams, CFErrorRef *error) {
+    NSDictionary *parametersForKeyExchange, *inputParameters = (__bridge NSDictionary *)inParams;
+    NSData *result;
+    NSMutableData *sharedInfoForKeyExchange;
 
     CFArrayAppendValue(context->algorithm, keyExchangeAlgorithm);
     context->operation = kSecKeyOperationTypeKeyExchange;
 
     if (context->mode == kSecKeyOperationModePerform) {
-        // Use 128bit AES for EC keys <= 256bit, 256bit AES for larger keys.
-        CFIndex keySize = ((CFDataGetLength(pubKey) - 1) / 2) * 8;
-        keySize = (keySize > 256) ? (256 / 8) : (128 / 8);
+        NSInteger keySize = 0;
+        NSNumber *keySizeObject = inputParameters[(__bridge id)kSecKeyEncryptionParameterSymmetricKeySizeInBits];
+        if (keySizeObject != nil) {
+            if (![keySizeObject isKindOfClass:NSNumber.class]) {
+                SecError(errSecParam, error, CFSTR("Bad requested kSecKeyEncryptionParameterSymmetricKeySizeInBits: %@"), keySizeObject);
+                return NULL;
+            }
+            keySize = keySizeObject.integerValue / 8;
+        } else {
+            // Use 128bit AES for EC keys <= 256bit, 256bit AES for larger keys.
+            keySize = ((CFDataGetLength(pubKey) - 1) / 2) * 8;
+            keySize = (keySize > 256) ? (256 / 8) : (128 / 8);
+        }
 
         if (variableIV) {
             keySize += sizeof(kSecKeyIESIV);
         }
 
         // Generate shared secret using KDF.
-        keySizeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &keySize);
-        parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
-                                                  kSecKeyKeyExchangeParameterSharedInfo, ephemeralPubKey,
-                                                  kSecKeyKeyExchangeParameterRequestedSize, keySizeRef,
-                                                  NULL);
+        sharedInfoForKeyExchange = ((__bridge NSData *)ephemeralPubKey).mutableCopy;
+        NSData *sharedInfo = inputParameters[(__bridge id)kSecKeyKeyExchangeParameterSharedInfo];
+        if (sharedInfo != nil) {
+            [sharedInfoForKeyExchange appendData:sharedInfo];
+        }
+        parametersForKeyExchange = @{ (__bridge id)kSecKeyKeyExchangeParameterSharedInfo: sharedInfoForKeyExchange,
+                                      (__bridge id)kSecKeyKeyExchangeParameterRequestedSize: @(keySize) };
     }
 
-    result = SecKeyRunAlgorithmAndCopyResult(context, encrypt ? pubKey : ephemeralPubKey, parameters, error);
+    result = CFBridgingRelease(SecKeyRunAlgorithmAndCopyResult(context, encrypt ? pubKey : ephemeralPubKey, (__bridge CFDictionaryRef)parametersForKeyExchange, error));
     if (context->mode == kSecKeyOperationModePerform && !variableIV && result != NULL) {
         // Append all-zero IV to the result.
-        CFMutableDataRef data = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, result);
-        CFDataAppendBytes(data, kSecKeyIESIV, sizeof(kSecKeyIESIV));
-        CFAssignRetained(result, data);
+        NSMutableData *data = result.mutableCopy;
+        [data appendBytes:kSecKeyIESIV length:sizeof(kSecKeyIESIV)];
+        result = [NSData dataWithData:data];
     }
-    CFReleaseSafe(parameters);
-    CFReleaseSafe(keySizeRef);
-    return result;
+    return CFBridgingRetain(result);
 }
 
-static Boolean SecKeyECIESEncryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFMutableDataRef result,
-                                                  CFErrorRef *error) {
+static Boolean SecKeyECIESEncryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams,
+                                                  CFMutableDataRef result, CFErrorRef *error) {
     Boolean res = FALSE;
     CFIndex prefix = CFDataGetLength(result);
     CFDataSetLength(result, prefix + CFDataGetLength(inData) + kSecKeyIESTagLength);
@@ -807,10 +822,11 @@ static Boolean SecKeyECIESEncryptAESGCMCopyResult(CFDataRef keyExchangeResult, C
     UInt8 *tagBuffer = resultBuffer + CFDataGetLength(inData);
     CFIndex aesKeySize = CFDataGetLength(keyExchangeResult) - sizeof(kSecKeyIESIV);
     const UInt8 *ivBuffer = CFDataGetBytePtr(keyExchangeResult) + aesKeySize;
+    CFDataRef aad = inParams ? CFDictionaryGetValue(inParams, kSecKeyEncryptionParameterSymmetricAAD) : NULL;
     require_action_quiet(ccgcm_one_shot(ccaes_gcm_encrypt_mode(),
                                         aesKeySize, CFDataGetBytePtr(keyExchangeResult),
                                         sizeof(kSecKeyIESIV), ivBuffer,
-                                        0, NULL,
+                                        aad ? CFDataGetLength(aad) : 0, aad ? CFDataGetBytePtr(aad) : NULL,
                                         CFDataGetLength(inData), CFDataGetBytePtr(inData),
                                         resultBuffer, kSecKeyIESTagLength, tagBuffer) == 0, out,
                          SecError(errSecParam, error, CFSTR("ECIES: Failed to aes-gcm encrypt data")));
@@ -819,7 +835,8 @@ out:
     return res;
 }
 
-static CFDataRef SecKeyECIESDecryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error) {
+static CFDataRef SecKeyECIESDecryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams,
+                                                    CFErrorRef *error) {
     CFDataRef result = NULL;
     CFMutableDataRef plaintext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData) - kSecKeyIESTagLength);
     CFMutableDataRef tag = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), kSecKeyIESTagLength);
@@ -827,10 +844,11 @@ static CFDataRef SecKeyECIESDecryptAESGCMCopyResult(CFDataRef keyExchangeResult,
                    CFDataGetMutableBytePtr(tag));
     CFIndex aesKeySize = CFDataGetLength(keyExchangeResult) - sizeof(kSecKeyIESIV);
     const UInt8 *ivBuffer = CFDataGetBytePtr(keyExchangeResult) + aesKeySize;
+    CFDataRef aad = inParams ? CFDictionaryGetValue(inParams, kSecKeyEncryptionParameterSymmetricAAD) : NULL;
     require_action_quiet(ccgcm_one_shot(ccaes_gcm_decrypt_mode(),
                                         aesKeySize, CFDataGetBytePtr(keyExchangeResult),
                                         sizeof(kSecKeyIESIV), ivBuffer,
-                                        0, NULL,
+                                        aad ? CFDataGetLength(aad) : 0, aad ? CFDataGetBytePtr(aad) : NULL,
                                         CFDataGetLength(plaintext), CFDataGetBytePtr(inData), CFDataGetMutableBytePtr(plaintext),
                                         kSecKeyIESTagLength, CFDataGetMutableBytePtr(tag)) == 0, out,
                          SecError(errSecParam, error, CFSTR("ECIES: Failed to aes-gcm decrypt data")));
@@ -877,7 +895,7 @@ ECIES_X963_ADAPTOR(SHA512, Cofactor, VariableIVX963, true)
 
 static CFDataRef SecKeyECIESKeyExchangeSHA2562PubKeysCopyResult(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
                                                                 bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey, bool variableIV,
-                                                                CFErrorRef *error) {
+                                                                CFDictionaryRef inParams, CFErrorRef *error) {
     CFArrayAppendValue(context->algorithm, keyExchangeAlgorithm);
     context->operation = kSecKeyOperationTypeKeyExchange;
     CFMutableDataRef result = (CFMutableDataRef)SecKeyRunAlgorithmAndCopyResult(context, ephemeralPubKey, NULL, error);
@@ -894,7 +912,8 @@ static CFDataRef SecKeyECIESKeyExchangeSHA2562PubKeysCopyResult(SecKeyOperationC
     return result;
 }
 
-static CFDataRef SecKeyECIESDecryptAESCBCCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error) {
+static CFDataRef SecKeyECIESDecryptAESCBCCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams,
+                                                    CFErrorRef *error) {
     CFMutableDataRef result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData));
     cccbc_one_shot(ccaes_cbc_decrypt_mode(),
                    CFDataGetLength(keyExchangeResult), CFDataGetBytePtr(keyExchangeResult),
index 774536a5062fcfbd9400306c27f55ab58cf48a1b..f04a136ea4e5aea5c9d1c4d83a0787395b26d633 100644 (file)
@@ -547,7 +547,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error)
         @autoreleasepool {
             os_transaction_t transaction = os_transaction_create("com.apple.trustd.PKITrustSupplementals.download");
             if (result != MADownloadSucceesful) {
-                MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MADownLoadResult", result,
+                MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MADownLoadResult", (OSStatus)result,
                                   @"failed to download catalog: %ld", (long)result);
                 if (result == MADownloadDaemonNotReady) {
                     /* mobileassetd has to wait for first unlock to downalod. trustd usually launches before first unlock. */
@@ -561,7 +561,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error)
             secnotice("OTATrust", "begin MobileAsset metadata sync request");
             MAQueryResult queryResult = [query queryMetaDataSync];
             if (queryResult != MAQuerySucceesful) {
-                MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MAQueryResult", queryResult,
+                MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MAQueryResult", (OSStatus)queryResult,
                                   @"failed to query MobileAsset metadata: %ld", (long)queryResult);
                 return;
             }
@@ -609,7 +609,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error)
                         updated_version = UpdateAndPurgeAsset(asset, asset_version, &ma_error);
                         break;
                     case MAUnknown:
-                        MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MAAssetState", asset.state,
+                        MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MAAssetState", (OSStatus)asset.state,
                                           @"asset is unknown");
                         continue;
                     case MADownloading:
@@ -622,7 +622,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error)
                             @autoreleasepool {
                                 os_transaction_t inner_transaction = os_transaction_create("com.apple.trustd.PKITrustSupplementals.downloadAsset");
                                 if (downloadResult != MADownloadSucceesful) {
-                                    MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MADownLoadResult", downloadResult,
+                                    MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MADownLoadResult", (OSStatus)downloadResult,
                                                       @"failed to download asset: %ld", (long)downloadResult);
                                     return;
                                 }
index 991f5a80278eb07569b740923fd1b3ea892b17aa..f7422fc26455697ceb1cff2277d446882d57230d 100644 (file)
@@ -554,23 +554,6 @@ static void test_key_sign(void) {
             return acData;
         };
 
-        blocks->copyObjectOperationAlgorithms = ^CFSetRef(CFDataRef oid, CFIndex operation, CFErrorRef *error) {
-            static NSSet *ops[] = {
-                [kSecKeyOperationTypeSign] = NULL,
-                [kSecKeyOperationTypeDecrypt] = NULL,
-                [kSecKeyOperationTypeKeyExchange] = NULL,
-            };
-
-            static dispatch_once_t onceToken;
-            dispatch_once(&onceToken, ^{
-                ops[kSecKeyOperationTypeSign] = [NSSet setWithArray:@[(id)kSecKeyAlgorithmECDSASignatureDigestX962]];
-                ops[kSecKeyOperationTypeDecrypt] = [NSSet setWithArray:@[(id)kSecKeyAlgorithmRSAEncryptionRaw]];
-                ops[kSecKeyOperationTypeKeyExchange] = [NSSet setWithArray:@[(id)kSecKeyAlgorithmECDHKeyExchangeCofactor]];
-            });
-
-            return CFBridgingRetain(ops[operation]);
-        };
-
         blocks->copyOperationResult = ^CFTypeRef(CFDataRef objectID, CFIndex operation, CFArrayRef algorithms, CFIndex secKeyOperationMode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
             SecKeyAlgorithm algorithm = CFArrayGetValueAtIndex(algorithms, CFArrayGetCount(algorithms) - 1);
             phase++;
index f747bf4567084c5a4530c95e66d954fab15ffb0c..b53cd556f59b5f54c0a48ba29307c9181888c9b9 100644 (file)
@@ -936,23 +936,19 @@ static void SecPolicyCheckBasicCertificateProcessing(SecPVCRef pvc,
            chain (root). */
         n--;
     } else {
-        /* trust may be restored for a path with an untrusted root that matches the allow list.
-           (isAllowlisted is set by revocation check, which is performed prior to path checks) */
-        if (!SecCertificatePathVCIsAllowlisted(path)) {
-            Boolean isSelfSigned = false;
-            (void) SecCertificateIsSelfSigned(SecCertificatePathVCGetCertificateAtIndex(path, n - 1), &isSelfSigned);
-            if (isSelfSigned) {
-                /* Add a detail for the root not being trusted. */
-                if (!SecPVCSetResultForced(pvc, kSecPolicyCheckAnchorTrusted,
-                                           n - 1, kCFBooleanFalse, true)) {
-                    return;
-                }
-            } else {
-                /* Add a detail for the missing intermediate. */
-                if (!SecPVCSetResultForced(pvc, kSecPolicyCheckMissingIntermediate,
-                                           n - 1, kCFBooleanFalse, true)) {
-                    return;
-                }
+        Boolean isSelfSigned = false;
+        (void) SecCertificateIsSelfSigned(SecCertificatePathVCGetCertificateAtIndex(path, n - 1), &isSelfSigned);
+        if (isSelfSigned) {
+            /* Add a detail for the root not being trusted. */
+            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckAnchorTrusted,
+                                       n - 1, kCFBooleanFalse, true)) {
+                return;
+            }
+        } else {
+            /* Add a detail for the missing intermediate. */
+            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckMissingIntermediate,
+                                       n - 1, kCFBooleanFalse, true)) {
+                return;
             }
         }
     }
@@ -2312,9 +2308,10 @@ static void SecPolicyCheckSystemTrustedCTRequired(SecPVCRef pvc) {
      *     Or the caller passed in the trusted log list. */
     require_quiet(SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable) || trustedLogs, out);
 
-    /*  2. Leaf issuance date is on or after 16 Oct 2018 at 00:00:00 AM UTC */
+    /*  2. Leaf issuance date is on or after 16 Oct 2018 at 00:00:00 AM UTC and not expired. */
     SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
-    require_quiet(SecCertificateNotValidBefore(leaf) >= 561340800.0, out);
+    require_quiet(SecCertificateNotValidBefore(leaf) >= 561340800.0 &&
+                  SecCertificateIsValid(leaf, SecPVCGetVerifyTime(pvc)), out);
 
     /*  3. Chain is anchored with root in the system anchor source but not the Apple anchor source */
     CFIndex count = SecPVCGetCertificateCount(pvc);
index 09eec204a15c9bb14fa8fdaf717d2b208a5bcdf6..d12695b2e337eba4b576fd4a85c7e951e0cf90af 100644 (file)
@@ -314,6 +314,8 @@ static ValidUpdateRequest *request = nil;
         config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.apple.trustd.networking.background"];
         config.networkServiceType = NSURLNetworkServiceTypeBackground;
         config.discretionary = YES;
+        config._requiresPowerPluggedIn = YES;
+        config.allowsCellularAccess = (!updateOnWiFiOnly) ? YES : NO;
     } else {
         config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; // no cookies or data storage
         config.networkServiceType = NSURLNetworkServiceTypeDefault;
@@ -327,10 +329,6 @@ static ValidUpdateRequest *request = nil;
     config.TLSMinimumSupportedProtocol = kTLSProtocol12;
     config.TLSMaximumSupportedProtocol = kTLSProtocol13;
 
-    config._requiresPowerPluggedIn = YES;
-
-    config.allowsCellularAccess = (!updateOnWiFiOnly) ? YES : NO;
-
     return config;
 }
 
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA2G1-Baltimore.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA2G1-Baltimore.cer
new file mode 100644 (file)
index 0000000..9e2b0a6
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA2G1-Baltimore.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-Baltimore.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-Baltimore.cer
new file mode 100644 (file)
index 0000000..06cb8e5
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-Baltimore.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-DigiCert.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-DigiCert.cer
new file mode 100644 (file)
index 0000000..3384c19
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/AppleISTCA8G1-DigiCert.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/BaltimoreCyberTrustRoot.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/BaltimoreCyberTrustRoot.cer
new file mode 100644 (file)
index 0000000..da96dbb
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/BaltimoreCyberTrustRoot.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/DigiCertGlobalRootG3.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/DigiCertGlobalRootG3.cer
new file mode 100644 (file)
index 0000000..6dda6a3
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/DigiCertGlobalRootG3.cer differ
index 9b6326acb2aeef36bb6c4755be024dd72f66303f..ea40b6d8496c6895262d1e6c06d5ea815c672a85 100644 (file)
                        <key>Properties</key>
                        <dict>
                                <key>SecPolicyName</key>
-                               <string>p04-fmip.icloud.com</string>
+                               <string>bbasile-test.scv.apple.com</string>
                        </dict>
                </dict>
                <key>Leaf</key>
-               <string>fmip</string>
+               <string>generic_apple_server</string>
                <key>Intermediates</key>
                <string>AppleServerAuthentication</string>
                <key>Anchors</key>
                <string>AppleRootCA</string>
                <key>VerifyDate</key>
-               <date>2016-04-18T19:00:00Z</date>
+               <date>2019-04-18T19:00:00Z</date>
                <key>ExpectedResult</key>
                <integer>5</integer>
        </dict>
                <key>Anchors</key>
                <string>AppleRootCA</string>
                <key>VerifyDate</key>
-               <date>2014-07-20T19:00:00Z</date>
+               <date>2019-07-20T19:00:00Z</date>
                <key>ExpectedResult</key>
                <integer>4</integer>
                <key>ChainLength</key>
                <key>ExpectedResult</key>
                <integer>5</integer>
        </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignPinning</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.74</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <string>AppleISTCA2G1-Baltimore</string>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignPinning</string>
+               <key>MinorTestName</key>
+               <string>BothPositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.74</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1</string>
+                       <string>AppleISTCA2G1-Baltimore</string>
+               </array>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignPinning</string>
+               <key>MinorTestName</key>
+               <string>BothPositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.74</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1</string>
+                       <string>AppleISTCA2G1-Baltimore</string>
+               </array>
+               <key>Anchors</key>
+               <string>GeoTrustGlobalCA</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSign</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.3</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <string>AppleISTCA2G1-Baltimore</string>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignCA8Baltimore</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.3</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>hls-svod.itunes.apple.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>itunes</string>
+               <key>Intermediates</key>
+               <string>AppleISTCA8G1-Baltimore</string>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignCA8DigiCert</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.3</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>hls-svod.itunes.apple.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>itunes</string>
+               <key>Intermediates</key>
+               <string>AppleISTCA8G1-DigiCert</string>
+               <key>Anchors</key>
+               <string>DigiCertGlobalRootG3</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSign</string>
+               <key>MinorTestName</key>
+               <string>BothPositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.3</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1-Baltimore</string>
+                       <string>AppleISTCA2G1</string>
+               </array>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>Anchors</key>
+               <string>GeoTrustGlobalCA</string>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSign</string>
+               <key>MinorTestName</key>
+               <string>BothPositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.3</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1-Baltimore</string>
+                       <string>AppleISTCA2G1</string>
+               </array>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignOldPin</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.74</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                               <key>SecPolicyPolicyName</key>
+                               <string>no-system-pinning-rules</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1-Baltimore</string>
+                       <string>AppleISTCA2G1</string>
+               </array>
+               <key>Anchors</key>
+               <string>GeoTrustGlobalCA</string>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>ISTCrossSignOldPin</string>
+               <key>MinorTestName</key>
+               <string>PositiveTest</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.74</string>
+                       <key>Properties</key>
+                       <dict>
+                               <key>SecPolicyName</key>
+                               <string>caldav.icloud.com</string>
+                               <key>SecPolicyPolicyName</key>
+                               <string>no-system-pinning-rules</string>
+                       </dict>
+               </dict>
+               <key>Leaf</key>
+               <string>caldav</string>
+               <key>Intermediates</key>
+               <array>
+                       <string>AppleISTCA2G1-Baltimore</string>
+                       <string>AppleISTCA2G1</string>
+               </array>
+               <key>Anchors</key>
+               <string>BaltimoreCyberTrustRoot</string>
+               <key>ExpectedResult</key>
+               <integer>5</integer>
+               <key>VerifyDate</key>
+               <date>2019-10-04T19:00:00Z</date>
+               <key>ChainLength</key>
+               <integer>3</integer>
+       </dict>
 </array>
 </plist>
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/caldav.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/caldav.cer
new file mode 100644 (file)
index 0000000..35b92cc
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/caldav.cer differ
index d38700210e7a9d85632f24e1654b1a489b6b518c..f91a14eb1ee7e29cada1cc1ed77e338420d38cab 100644 (file)
Binary files a/OSX/shared_regressions/si-20-sectrust-policies-data/generic_apple_server.cer and b/OSX/shared_regressions/si-20-sectrust-policies-data/generic_apple_server.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/itunes.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/itunes.cer
new file mode 100644 (file)
index 0000000..c1681b6
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/itunes.cer differ
index a6568eea6279815aecbe6879ce6071640f40898a..16632ba6fd27031b0e11b02bfedbf787d85112a1 100644 (file)
@@ -6,6 +6,8 @@
 #import <Security/Security.h>
 #import <Security/SecItemPriv.h>
 #import <Security/SecKeyPriv.h>
+#import <Security/SecAccessControlPriv.h>
+#import <libaks_acl_cf_keys.h>
 #if !TARGET_OS_OSX
 #import "MobileGestalt.h"
 #else
 
 #import "shared_regressions.h"
 
-static id generateKey(id keyType, CFStringRef protection) {
-    id accessControl = (__bridge_transfer id)SecAccessControlCreateWithFlags(NULL, protection, kSecAccessControlPrivateKeyUsage, NULL);
+static id generateKey(id keyType, CFStringRef protection, BOOL noACL) {
+    id accessControl;
+    if (noACL) {
+        accessControl = CFBridgingRelease(SecAccessControlCreate(kCFAllocatorDefault, NULL));
+        SecAccessControlSetProtection((__bridge SecAccessControlRef)accessControl, protection, NULL);
+    } else {
+        accessControl = CFBridgingRelease(SecAccessControlCreateWithFlags(NULL, protection, kSecAccessControlPrivateKeyUsage, NULL));
+    }
     NSDictionary *keyAttributes = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore,
                                      (id)kSecAttrKeyType : keyType,
                                      (id)kSecAttrAccessControl : accessControl,
@@ -33,8 +41,9 @@ static void secKeySepTest(BOOL testPKA) {
     } else {
         keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeSecureEnclaveAttestation];
     }
+    BOOL noACL = YES;
     for (id keyType in keyTypes) {
-        id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly);
+        id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (noACL = !noACL));
         ok(privateKey, "failed to create key '%@'", keyType);
         id publicKey = (__bridge_transfer id)SecKeyCopyPublicKey((SecKeyRef)privateKey);
 
@@ -83,10 +92,10 @@ static void secKeySepTest(BOOL testPKA) {
     }
 }
 
-static void attestationTest(CFStringRef protection) {
+static void attestationTest(CFStringRef protection, BOOL noACL) {
     NSError *error;
-    id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection);
-    id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection);
+    id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, noACL);
+    id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection, noACL);
     id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error));
     ok(sik != nil, "get SIK key: %@", error);
 
@@ -178,6 +187,215 @@ static void attestationTest(CFStringRef protection) {
     }
 }
 
+static const uint8_t satori_pub[] = {
+    0x04, 0xe4, 0xef, 0x00, 0x27, 0xcb, 0xa6, 0x46, 0x0d, 0xa6, 0xbd, 0x77, 0x14, 0x65, 0xe5, 0x5a,
+    0x14, 0xc9, 0xf8, 0xd8, 0xdd, 0x4c, 0x70, 0x44, 0x50, 0x49, 0xe4, 0xfa, 0x24, 0x71, 0xaa, 0x4c,
+    0xe2, 0x74, 0x3b, 0xfd, 0x23, 0xda, 0x6f, 0x92, 0x04, 0x4c, 0x93, 0x6c, 0xea, 0x8a, 0xac, 0x22,
+    0x99, 0xd9, 0x6e, 0x3f, 0xed, 0x20, 0xfd, 0xdd, 0x95, 0xe2, 0x32, 0xa0, 0xeb, 0x23, 0xa2, 0xd2,
+    0x8b
+};
+
+static const uint8_t satori_priv[] = {
+    0x04, 0xe4, 0xef, 0x00, 0x27, 0xcb, 0xa6, 0x46,
+    0x0d, 0xa6, 0xbd, 0x77, 0x14, 0x65, 0xe5, 0x5a, 0x14, 0xc9, 0xf8, 0xd8, 0xdd, 0x4c, 0x70, 0x44,
+    0x50, 0x49, 0xe4, 0xfa, 0x24, 0x71, 0xaa, 0x4c, 0xe2, 0x74, 0x3b, 0xfd, 0x23, 0xda, 0x6f, 0x92,
+    0x04, 0x4c, 0x93, 0x6c, 0xea, 0x8a, 0xac, 0x22, 0x99, 0xd9, 0x6e, 0x3f, 0xed, 0x20, 0xfd, 0xdd,
+    0x95, 0xe2, 0x32, 0xa0, 0xeb, 0x23, 0xa2, 0xd2, 0x8b, 0x23, 0xcf, 0x74, 0xb4, 0x76, 0x93, 0xdf,
+    0x6d, 0x31, 0x63, 0xc9, 0x87, 0x85, 0x3f, 0x44, 0x09, 0x1f, 0x0d, 0xe2, 0x9a, 0x94, 0x29, 0x03,
+    0x70, 0xbf, 0x87, 0x2a, 0x7e, 0xac, 0xa8, 0x8d, 0x11,
+};
+
+static const uint8_t satori_test_cert[] = {
+    0x30, 0x82, 0x03, 0xf2, 0x30, 0x82, 0x03, 0x98, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x75,
+    0x0e, 0x97, 0x07, 0xb3, 0x6e, 0x48, 0xe9, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x04, 0x03, 0x02, 0x30, 0x7f, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2a,
+    0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69,
+    0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69,
+    0x6f, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
+    0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+    0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+    0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70,
+    0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+    0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x39, 0x32, 0x37, 0x31, 0x38,
+    0x33, 0x31, 0x30, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x30, 0x32, 0x36, 0x31, 0x38, 0x33,
+    0x31, 0x30, 0x37, 0x5a, 0x30, 0x73, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89,
+    0x93, 0xf2, 0x2c, 0x64, 0x01, 0x01, 0x0c, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x31,
+    0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53,
+    0x50, 0x20, 0x4c, 0x65, 0x61, 0x66, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+    0x19, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x36, 0x33, 0x35, 0x2e,
+    0x31, 0x30, 0x30, 0x2e, 0x36, 0x2e, 0x36, 0x34, 0x2e, 0x33, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+    0x55, 0x04, 0x0a, 0x0c, 0x07, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x50, 0x31, 0x0b, 0x30, 0x09,
+    0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+    0x03, 0x42, 0x00, 0x04, 0xe4, 0xef, 0x00, 0x27, 0xcb, 0xa6, 0x46, 0x0d, 0xa6, 0xbd, 0x77, 0x14,
+    0x65, 0xe5, 0x5a, 0x14, 0xc9, 0xf8, 0xd8, 0xdd, 0x4c, 0x70, 0x44, 0x50, 0x49, 0xe4, 0xfa, 0x24,
+    0x71, 0xaa, 0x4c, 0xe2, 0x74, 0x3b, 0xfd, 0x23, 0xda, 0x6f, 0x92, 0x04, 0x4c, 0x93, 0x6c, 0xea,
+    0x8a, 0xac, 0x22, 0x99, 0xd9, 0x6e, 0x3f, 0xed, 0x20, 0xfd, 0xdd, 0x95, 0xe2, 0x32, 0xa0, 0xeb,
+    0x23, 0xa2, 0xd2, 0x8b, 0xa3, 0x82, 0x02, 0x08, 0x30, 0x82, 0x02, 0x04, 0x30, 0x0c, 0x06, 0x03,
+    0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+    0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb9, 0x04, 0x1a, 0x95, 0x5b, 0x6b, 0x91, 0x04, 0x39,
+    0xea, 0x70, 0x2a, 0x47, 0xb7, 0xa8, 0x49, 0x36, 0xe4, 0x4d, 0xdb, 0x30, 0x4d, 0x06, 0x08, 0x2b,
+    0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x41, 0x30, 0x3f, 0x30, 0x3d, 0x06, 0x08, 0x2b,
+    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+    0x6f, 0x63, 0x73, 0x70, 0x2d, 0x75, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x33, 0x2d, 0x74,
+    0x73, 0x61, 0x61, 0x69, 0x63, 0x61, 0x67, 0x33, 0x31, 0x30, 0x30, 0x82, 0x01, 0x03, 0x06, 0x03,
+    0x55, 0x1d, 0x20, 0x04, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30, 0x81, 0xf5, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, 0x81, 0xe7, 0x30, 0x81, 0xac, 0x06, 0x08, 0x2b,
+    0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x81, 0x9f, 0x0c, 0x81, 0x9c, 0x52, 0x65, 0x6c,
+    0x69, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x65,
+    0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x62, 0x79, 0x20, 0x61, 0x6e, 0x79,
+    0x20, 0x70, 0x61, 0x72, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63,
+    0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+    0x63, 0x61, 0x74, 0x65, 0x20, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2c, 0x20, 0x43, 0x65, 0x72,
+    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x72, 0x61, 0x63, 0x74,
+    0x69, 0x63, 0x65, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61,
+    0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20,
+    0x61, 0x6e, 0x79, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61,
+    0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x30, 0x36, 0x06, 0x08, 0x2b, 0x06, 0x01,
+    0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,
+    0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74,
+    0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
+    0x2f, 0x30, 0x3c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x35, 0x30, 0x33, 0x30, 0x31, 0xa0, 0x2f,
+    0xa0, 0x2d, 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2d, 0x75,
+    0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+    0x6d, 0x2f, 0x74, 0x73, 0x61, 0x61, 0x69, 0x63, 0x61, 0x67, 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x30,
+    0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa0, 0xe6, 0xdf, 0x03, 0xb1, 0x2a,
+    0x53, 0x40, 0x35, 0xc4, 0x01, 0x4b, 0x6a, 0xbd, 0x35, 0x8f, 0x6d, 0x28, 0x63, 0xba, 0x30, 0x0e,
+    0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x03, 0x28, 0x30, 0x10,
+    0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x40, 0x03, 0x04, 0x02, 0x05, 0x00,
+    0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30,
+    0x45, 0x02, 0x20, 0x6a, 0x7e, 0xf1, 0x0b, 0x60, 0xba, 0x4c, 0x3c, 0x83, 0xd5, 0xbd, 0x4a, 0xb1,
+    0x62, 0x2f, 0x52, 0x92, 0xba, 0xb9, 0x64, 0xcd, 0xaa, 0x63, 0x96, 0xa6, 0xd8, 0x6d, 0x3a, 0xf3,
+    0x83, 0x81, 0xb9, 0x02, 0x21, 0x00, 0xc2, 0x37, 0x2d, 0x3a, 0xb7, 0x03, 0x81, 0x2f, 0x3e, 0xf1,
+    0x32, 0x98, 0x43, 0x27, 0xbb, 0x64, 0xbf, 0xfb, 0xb9, 0x9a, 0x0c, 0xad, 0x9a, 0x98, 0x6f, 0xbc,
+    0x87, 0x30, 0xfe, 0xfe, 0x3c, 0x2e, 0x30, 0x82, 0x03, 0x17, 0x30, 0x82, 0x02, 0x9e, 0xa0, 0x03,
+    0x02, 0x01, 0x02, 0x02, 0x08, 0x5b, 0x7d, 0xce, 0x90, 0x32, 0x77, 0x34, 0xd6, 0x30, 0x0a, 0x06,
+    0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x6c, 0x31, 0x20, 0x30, 0x1e, 0x06,
+    0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65,
+    0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30,
+    0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65,
+    0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
+    0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a,
+    0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+    0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x35, 0x33,
+    0x30, 0x32, 0x31, 0x33, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x30, 0x35, 0x32, 0x36,
+    0x32, 0x31, 0x33, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x7f, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55,
+    0x04, 0x03, 0x0c, 0x2a, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x41,
+    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67,
+    0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26,
+    0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43,
+    0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
+    0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+    0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06,
+    0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+    0x42, 0x00, 0x04, 0xfa, 0xdc, 0xcc, 0x11, 0x10, 0x74, 0x7b, 0x30, 0xc4, 0x69, 0xdd, 0x65, 0xc3,
+    0xda, 0xa1, 0x55, 0xdf, 0xeb, 0x09, 0x5c, 0x29, 0xd0, 0x50, 0x3e, 0x1c, 0x0a, 0x34, 0xfa, 0x83,
+    0xb1, 0x79, 0x49, 0x4d, 0x9d, 0xb3, 0xb9, 0x46, 0xa1, 0xc9, 0x43, 0x67, 0xb3, 0x03, 0x45, 0xd3,
+    0xa4, 0x01, 0x60, 0xc3, 0x58, 0xdb, 0x98, 0x83, 0x19, 0x32, 0xce, 0xc5, 0xa3, 0x68, 0x38, 0xb6,
+    0xca, 0x4d, 0x63, 0xa3, 0x82, 0x01, 0x15, 0x30, 0x82, 0x01, 0x11, 0x30, 0x53, 0x06, 0x08, 0x2b,
+    0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x47, 0x30, 0x45, 0x30, 0x43, 0x06, 0x08, 0x2b,
+    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x37, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+    0x6f, 0x63, 0x73, 0x70, 0x2d, 0x75, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, 0x2d, 0x74,
+    0x65, 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, 0x67, 0x33,
+    0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb9, 0x04, 0x1a, 0x95, 0x5b,
+    0x6b, 0x91, 0x04, 0x39, 0xea, 0x70, 0x2a, 0x47, 0xb7, 0xa8, 0x49, 0x36, 0xe4, 0x4d, 0xdb, 0x30,
+    0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
+    0x02, 0x01, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+    0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, 0xdf, 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44,
+    0x67, 0x17, 0x1b, 0x46, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x3d, 0x30, 0x3b, 0x30,
+    0x39, 0xa0, 0x37, 0xa0, 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72,
+    0x6c, 0x2d, 0x75, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65,
+    0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f,
+    0x6f, 0x74, 0x63, 0x61, 0x67, 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+    0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x0e, 0x04, 0x02, 0x05, 0x00, 0x30, 0x0a, 0x06, 0x08,
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, 0x30, 0x64, 0x02, 0x30, 0x6a,
+    0x26, 0x0d, 0x2a, 0x80, 0xcd, 0x69, 0x33, 0xef, 0x50, 0xbb, 0x78, 0xbc, 0x17, 0x4c, 0xcd, 0xa6,
+    0x6b, 0x86, 0xe2, 0x86, 0xd3, 0xe7, 0x3d, 0xc3, 0x8f, 0x01, 0xd8, 0x83, 0xe6, 0xc8, 0x1c, 0x7d,
+    0xe7, 0x78, 0xca, 0xfd, 0x29, 0xd5, 0xfa, 0x32, 0x63, 0x98, 0xdb, 0x65, 0x17, 0x2e, 0x05, 0x02,
+    0x30, 0x4d, 0xd7, 0x31, 0x32, 0xfa, 0x17, 0x73, 0x50, 0x9c, 0xb6, 0x04, 0x1d, 0xca, 0xa6, 0x1f,
+    0x60, 0x0a, 0x72, 0x59, 0x6d, 0x7f, 0xc9, 0x5b, 0x93, 0x4a, 0x13, 0x40, 0x60, 0xae, 0x6c, 0x13,
+    0x43, 0xd2, 0x71, 0xc2, 0xdd, 0x32, 0xaa, 0x90, 0xa9, 0xc5, 0xe2, 0xdd, 0x32, 0x23, 0x2f, 0xaa,
+    0xda, 0x30, 0x82, 0x02, 0x4c, 0x30, 0x82, 0x01, 0xd3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08,
+    0x78, 0x36, 0x0b, 0xf4, 0xb7, 0xc8, 0xb6, 0xb0, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
+    0x3d, 0x04, 0x03, 0x03, 0x30, 0x6c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+    0x17, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74,
+    0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04,
+    0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+    0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
+    0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65,
+    0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x32, 0x32, 0x30, 0x33, 0x31, 0x37,
+    0x34, 0x34, 0x5a, 0x17, 0x0d, 0x34, 0x30, 0x31, 0x32, 0x32, 0x36, 0x30, 0x33, 0x31, 0x33, 0x33,
+    0x37, 0x5a, 0x30, 0x6c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54,
+    0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
+    0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+    0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
+    0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13,
+    0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49,
+    0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+    0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,
+    0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xa9, 0x1a, 0x63, 0x34, 0xef, 0xbc, 0xa6, 0x8a,
+    0xd6, 0x2a, 0x6a, 0x38, 0x22, 0xe9, 0x25, 0xad, 0xda, 0x28, 0xa0, 0x49, 0xc5, 0x64, 0xfe, 0x5d,
+    0x91, 0xc3, 0x6c, 0xf7, 0x99, 0xe4, 0xba, 0xe4, 0x2a, 0x5f, 0x61, 0xd2, 0xbf, 0x3b, 0x6c, 0xa8,
+    0x61, 0x11, 0xb5, 0xe0, 0x66, 0xf7, 0x22, 0x11, 0x86, 0x97, 0x5d, 0xc3, 0xba, 0x1b, 0x6d, 0x55,
+    0x7f, 0xd0, 0xf9, 0x80, 0xe0, 0xff, 0xd9, 0x05, 0xad, 0x5a, 0x5b, 0xbf, 0x3a, 0x7a, 0xa7, 0x09,
+    0x52, 0x1a, 0x31, 0x7f, 0x0c, 0xa2, 0xe8, 0x10, 0xf5, 0x36, 0xd3, 0xc8, 0xea, 0xa0, 0x5b, 0x0a,
+    0x28, 0x85, 0x30, 0x28, 0x5f, 0x94, 0xf6, 0x94, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03,
+    0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc,
+    0xdf, 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x30, 0x0f, 0x06, 0x03, 0x55,
+    0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03,
+    0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08,
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x67, 0x00, 0x30, 0x64, 0x02, 0x30, 0x1a,
+    0x14, 0x38, 0x24, 0xff, 0xb4, 0x08, 0xcb, 0xea, 0xc9, 0x3b, 0xda, 0xcc, 0x82, 0xf3, 0xd9, 0x0d,
+    0xd1, 0x2b, 0x6e, 0xbf, 0x1f, 0xc4, 0x15, 0x14, 0x44, 0xdf, 0x98, 0x9b, 0xd7, 0xdd, 0xba, 0x1b,
+    0xbe, 0x4f, 0x9f, 0x17, 0xa4, 0xd2, 0x02, 0x75, 0x90, 0x7d, 0x76, 0xcc, 0x93, 0x16, 0x2f, 0x02,
+    0x30, 0x02, 0xd7, 0xda, 0x0b, 0xbe, 0xdd, 0x3d, 0xed, 0xf9, 0xa3, 0x06, 0x90, 0xa9, 0x58, 0xbd,
+    0x6b, 0x7c, 0x7c, 0xe5, 0xc5, 0x4e, 0x0e, 0x44, 0xa2, 0x94, 0x2f, 0xb4, 0x04, 0x9a, 0xcd, 0x9b,
+    0x69, 0x8d, 0x2a, 0xc6, 0x1d, 0x58, 0xff, 0xe3, 0x32, 0xb6, 0xdb, 0x3e, 0x34, 0xff, 0x67, 0x70,
+    0xf1
+};
+
+static void rewrapTest(void) {
+    id accessControl;
+    accessControl = CFBridgingRelease(SecAccessControlCreate(kCFAllocatorDefault, NULL));
+    SecAccessControlSetProtection((__bridge SecAccessControlRef)accessControl, kSecAttrAccessibleWhenUnlocked, NULL);
+    SecAccessControlSetConstraints((__bridge SecAccessControlRef)accessControl, (__bridge CFDictionaryRef)@{(id)kAKSKeyOpECIESTranscode: @YES});
+
+    NSDictionary *keyAttributes = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore,
+                                     (id)kSecAttrKeyType : (id)kSecAttrKeyTypeECSECPrimeRandom,
+                                     (id)kSecKeyApplePayEnabled: @YES,
+                                     (id)kSecAttrAccessControl : accessControl,
+                                     (id)kSecAttrIsPermanent : @NO };
+    NSError *error;
+    id key = (__bridge_transfer id)SecKeyCreateRandomKey((CFDictionaryRef)keyAttributes, (void *)&error);
+    ok(key, "failed to create random key %@", error);
+
+    // Encrypt message with SEP key.
+    NSData *message = [@"message" dataUsingEncoding:NSUTF8StringEncoding];
+    id pubKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)key));
+    NSData *encrypted = CFBridgingRelease(SecKeyCreateEncryptedDataWithParameters((__bridge SecKeyRef)pubKey, kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM, (__bridge CFDataRef)message, (__bridge CFDictionaryRef)@{(id)kSecKeyEncryptionParameterSymmetricKeySizeInBits: @256}, (void *)&error));
+    ok(encrypted, "failed to encrypt with public key, %@", error);
+    NSData *cert = [NSData dataWithBytes:satori_test_cert length:sizeof(satori_test_cert)];
+    NSDictionary *recryptParams = @{
+                                    (id)kSecKeyEncryptionParameterRecryptCertificate: cert,
+                                    (id)kSecKeyEncryptionParameterSymmetricKeySizeInBits: @256,
+                                    (id)kSecKeyEncryptionParameterRecryptParameters: @{
+                                            (id)kSecKeyEncryptionParameterSymmetricKeySizeInBits: @256
+                                            },
+                                    };
+    NSData *recrypted = CFBridgingRelease(SecKeyCreateDecryptedDataWithParameters((__bridge SecKeyRef)key, kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM, (__bridge CFDataRef)encrypted, (__bridge CFDictionaryRef)recryptParams, (void *)&error));
+    ok(recrypted, "failed to recrypt, %@", error);
+
+    id recryptKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)[NSData dataWithBytes:satori_priv length:sizeof(satori_priv)], (CFDictionaryRef)@{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate}, (void *)&error));
+    NSData *decrypted = CFBridgingRelease(SecKeyCreateDecryptedDataWithParameters((__bridge SecKeyRef)recryptKey, kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM, (__bridge CFDataRef)recrypted, (__bridge CFDictionaryRef)@{(id)kSecKeyEncryptionParameterSymmetricKeySizeInBits: @256}, (void *)&error));
+    ok(decrypted, "failed to decrypt, %@", error);
+    ok([decrypted isEqualToData:message], "Decrypted data differs: %@ vs %@", decrypted, message);
+}
+
 int si_44_seckey_aks(int argc, char *const *argv) {
     @autoreleasepool {
         BOOL testPKA = YES;
@@ -196,10 +414,16 @@ int si_44_seckey_aks(int argc, char *const *argv) {
 
         testPKA = NO;
 #endif
-        plan_tests(testPKA ? 95 : 80);
+        plan_tests(testPKA ? 100 : 85);
+
+        // Put SEP keys into test-keybag mode. Available only when running in direct-mode, not with extension.
+        SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanTrue, NULL);
+        rewrapTest();
+        SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanFalse, NULL);
+
         secKeySepTest(testPKA);
-        attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly);
-        attestationTest(kSecAttrAccessibleUntilReboot);
+        attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, NO);
+        attestationTest(kSecAttrAccessibleUntilReboot, YES);
         return 0;
     }
 }
index 27980924832f1b905a11b0c14c5208ad9fd250ae..cb47776913519d584f6b23e4c7bd386ef70bf16f 100644 (file)
@@ -24,6 +24,7 @@
 
 #import <Foundation/Foundation.h>
 #import <Security/SecItemPriv.h>
+#import <Security/SecKeyPriv.h>
 
 #import <corecrypto/ccrng.h>
 #import <corecrypto/ccsha1.h>
@@ -48,14 +49,19 @@ static void test_ies_run(id privateKey, SecKeyAlgorithm algorithm) {
        "%@ not supported for encryption - privKey", algorithm);
 
     NSData *message = [NSData dataWithBytes:"hello" length:5];
+    NSDictionary *sharedInfo = @{(id)kSecKeyKeyExchangeParameterSharedInfo :[NSData dataWithBytes:"shared" length:6]};
     error = nil;
     NSData *encrypted = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)message, (void *)&error));
+    NSData *encryptedSI = CFBridgingRelease(SecKeyCreateEncryptedDataWithParameters((__bridge SecKeyRef)publicKey, algorithm, (__bridge CFDataRef)message, (__bridge CFDictionaryRef)sharedInfo, (void *)&error));
     ok(encrypted, "message encrypted");
 
     error = nil;
     NSData *decrypted = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privateKey, algorithm, (CFDataRef)encrypted, (void *)&error));
     ok(decrypted, "encrypted message decrypted");
     ok([decrypted isEqual:message], "decrypted message is equal as original one (original:%@ decrypted:%@)", message, decrypted);
+    NSData *decryptedSI = CFBridgingRelease(SecKeyCreateDecryptedDataWithParameters((__bridge SecKeyRef)privateKey, algorithm, (__bridge CFDataRef)encryptedSI, (__bridge CFDictionaryRef)sharedInfo, (void *)&error));
+    ok(decryptedSI, "encrypted-with-sharedinfo message decrypted: %@", error);
+    ok([decryptedSI isEqual:message], "decrypted-with-sharedinfo message is equal as original one (original:%@ decrypted:%@)", message, decryptedSI);
 
     // Modify encrypted message and verify that it cannot be decrypted.
     NSMutableData *badEncrypted = [NSMutableData dataWithData:encrypted];
@@ -90,7 +96,7 @@ static void test_ies_run(id privateKey, SecKeyAlgorithm algorithm) {
     decrypted = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privateKey, algorithm, (CFDataRef)badEncrypted, (void *)&error));
     ok(decrypted == nil, "broken encrypted message failed to decrypt (pubkey data breakage)");
 }
-static const int TestCountIESRun = 12;
+static const int TestCountIESRun = 14;
 
 static void test_ecies() {
     NSError *error;
@@ -170,6 +176,30 @@ static void test_ies_against_corecrypto(id privKey, ccec_const_cp_t cp, const st
     // SecKey encrypt -> cc decrypt.
     static const UInt8 knownPlaintext[] = "KNOWN PLAINTEXT";
     NSData *plaintext = [NSData dataWithBytes:knownPlaintext length:sizeof(knownPlaintext)];
+    static const UInt8 knownSharedInfo[] = "SHARED INFO";
+    NSData *sharedInfo = [NSData dataWithBytes:knownSharedInfo length:sizeof(knownSharedInfo)];
+    static const UInt8 knownSharedInfo2[] = "2SHARED INFO2";
+    NSData *sharedInfo2 = [NSData dataWithBytes:knownSharedInfo2 length:sizeof(knownSharedInfo2)];
+    NSMutableDictionary *parameters = @{(id)kSecKeyKeyExchangeParameterSharedInfo: sharedInfo,
+                                        (id)kSecKeyEncryptionParameterSymmetricAAD: sharedInfo2,
+                                        }.mutableCopy;
+
+    static int keyCounter = 0;
+    keyCounter++;
+    uint32_t ccKeySizeSI = ccKeySize;
+    switch (keyCounter % 3) {
+        case 0:
+            break;
+        case 1:
+            ccKeySizeSI = 16;
+            parameters[(id)kSecKeyEncryptionParameterSymmetricKeySizeInBits] = @(ccKeySizeSI * 8);
+            break;
+        case 2:
+            ccKeySizeSI = 32;
+            parameters[(id)kSecKeyEncryptionParameterSymmetricKeySizeInBits] = @(ccKeySizeSI * 8);
+            break;
+    }
+
     error = nil;
     id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privKey));
     NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)plaintext, (void *)&error));
@@ -179,13 +209,22 @@ static void test_ies_against_corecrypto(id privKey, ccec_const_cp_t cp, const st
                               ECIES_EPH_PUBKEY_IN_SHAREDINFO1 | ECIES_EXPORT_PUB_STANDARD | (secureIV ? 0 : ECIES_LEGACY_IV));
     size_t decryptedLength = plaintext.length;
     NSMutableData *decrypted = [NSMutableData dataWithLength:decryptedLength];
-    if (ciphertext != nil) {
-        ok(ccecies_decrypt_gcm(fullkey, &ecies_dec, ciphertext.length, ciphertext.bytes, 0, NULL, 0, NULL,
-                               &decryptedLength, decrypted.mutableBytes) == 0, "decrypt data with cc failed");
-    }
+    ok(ccecies_decrypt_gcm(fullkey, &ecies_dec, ciphertext.length, ciphertext.bytes, 0, NULL, 0, NULL,
+                           &decryptedLength, decrypted.mutableBytes) == 0, "decrypt data with cc failed");
     ok(decryptedLength = plaintext.length);
     ok([plaintext isEqualToData:decrypted], "cc decrypted data are the same");
 
+    NSData *ciphertextSI = CFBridgingRelease(SecKeyCreateEncryptedDataWithParameters((__bridge SecKeyRef)publicKey, algorithm, (__bridge CFDataRef)plaintext, (__bridge CFDictionaryRef)parameters, (void *)&error));
+    ok(ciphertextSI != nil, "encrypt-with-sharedinfo data with SecKey (error %@)", error);
+    struct ccecies_gcm ecies_dec_SI;
+    ccecies_decrypt_gcm_setup(&ecies_dec_SI, di, ccaes_gcm_decrypt_mode(), ccKeySizeSI, 16,
+                              ECIES_EPH_PUBKEY_AND_SHAREDINFO1 | ECIES_EXPORT_PUB_STANDARD | (secureIV ? 0 : ECIES_LEGACY_IV));
+    NSMutableData *decryptedSI = [NSMutableData dataWithLength:decryptedLength];
+    ok(ccecies_decrypt_gcm(fullkey, &ecies_dec_SI, ciphertextSI.length, ciphertextSI.bytes, sizeof(knownSharedInfo), knownSharedInfo,
+                           sizeof(knownSharedInfo2), knownSharedInfo2, &decryptedLength, decryptedSI.mutableBytes) == 0, "decrypt-with-sharedinfo data with cc failed");
+    ok(decryptedLength = plaintext.length);
+    ok([plaintext isEqualToData:decryptedSI], "cc decrypted-with-sharedinfo data are the same");
+
     // cc encrypt -> SecKey decrypt
     struct ccecies_gcm ecies_enc;
     ccecies_encrypt_gcm_setup(&ecies_enc, di, ccrng(NULL), ccaes_gcm_encrypt_mode(), ccKeySize, 16,
@@ -197,8 +236,17 @@ static void test_ies_against_corecrypto(id privKey, ccec_const_cp_t cp, const st
     NSData *decryptedPlaintext = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privKey, algorithm, (CFDataRef)encrypted, (void *)&error));
     ok(decryptedPlaintext != nil, "decrypt data with SecKey (error %@)", error);
     ok([plaintext isEqualToData:decryptedPlaintext], "SecKey decrypted data are the same");
+
+    struct ccecies_gcm ecies_enc_SI;
+    ccecies_encrypt_gcm_setup(&ecies_enc_SI, di, ccrng(NULL), ccaes_gcm_encrypt_mode(), ccKeySizeSI, 16,
+                              ECIES_EPH_PUBKEY_AND_SHAREDINFO1 | ECIES_EXPORT_PUB_STANDARD | (secureIV ? 0 : ECIES_LEGACY_IV));
+    NSMutableData *encryptedSI = [NSMutableData dataWithLength:encryptedLength];
+    ok(ccecies_encrypt_gcm(ccec_ctx_pub(fullkey), &ecies_enc_SI, sizeof(knownPlaintext), knownPlaintext, sizeof(knownSharedInfo), knownSharedInfo, sizeof(knownSharedInfo2), knownSharedInfo2, &encryptedLength, encryptedSI.mutableBytes) == 0, "encrypt-with-sharedinfo data with cc failed");
+    NSData *decryptedPlaintextSI = CFBridgingRelease(SecKeyCreateDecryptedDataWithParameters((__bridge SecKeyRef)privKey, algorithm, (__bridge CFDataRef)encryptedSI, (__bridge CFDictionaryRef)parameters, (void *)&error));
+    ok(decryptedPlaintextSI != nil, "decrypt-with-sharedinfo data with SecKey (error %@)", error);
+    ok([plaintext isEqualToData:decryptedPlaintextSI], "SecKey decrypted-with-sharedinfo data are the same");
 }
-static const int TestCountIESAgainstCoreCryptoRun = 9;
+static const int TestCountIESAgainstCoreCryptoRun = 16;
 
 static void test_against_corecrypto() {
     id privKey;
index 355148964c06a9c8bb965ec63a0925e3f09ef36f..10ae842412409c1ac08e282365d3ffc29a594dc8 100644 (file)
@@ -674,6 +674,7 @@ static void test_enforcement(void) {
     SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
     NSArray *anchors = nil, *keychain_certs = nil;
     NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
+    NSDate *expiredDate = [NSDate dateWithTimeIntervalSinceReferenceDate:570000000.0]; // January 24, 2019 at 12:20:00 AM EST
     CFErrorRef error = nil;
     CFDataRef exceptions = nil;
 
@@ -713,6 +714,11 @@ static void test_enforcement(void) {
         fail("expected trust evaluation to fail and it did not.");
     }
 
+    // test expired system cert after date without CT passes with only expiration error
+    require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)expiredDate), errOut, fail("failed to set verify date"));
+    ok(SecTrustIsExpiredOnly(trust), "expired system post-flag-date non-CT cert had non-expiration errors");
+    require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
+
     // test exceptions for failing cert passes
     exceptions = SecTrustCopyExceptions(trust);
     ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
@@ -1421,7 +1427,7 @@ static void test_ct_exceptions(void) {
 
 int si_82_sectrust_ct(int argc, char *const *argv)
 {
-       plan_tests(432);
+       plan_tests(433);
 
        tests();
     test_sct_serialization();
index f19f5413548b7078540110c3647cacc47ada2d08..4260ed2107393e5abdd6593baf5f7c8dc89cfcc8 100644 (file)
@@ -795,7 +795,7 @@ static sqlite3 *_SecDbOpenV2(const char *path,
     } else if (SQLITE_OPEN_READWRITE == (flags & SQLITE_OPEN_READWRITE)) {
         if (useRobotVacuum) {
 #define SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL 2
-            sqlite3_stmt *stmt;
+            sqlite3_stmt *stmt = NULL;
             int vacuumMode = -1;
 
             /*
@@ -812,6 +812,7 @@ static sqlite3 *_SecDbOpenV2(const char *path,
                 }
                 sqlite3_reset(stmt);
             }
+            sqlite3_finalize(stmt);
 
             if (vacuumMode != SECDB_SQLITE_AUTO_VACUUM_INCREMENTAL) {
                 (void)sqlite3_exec(handle, "PRAGMA auto_vacuum = incremental", NULL, NULL, NULL);
@@ -1284,7 +1285,10 @@ SecDbConnectionDestroy(CFTypeRef value)
 {
     SecDbConnectionRef dbconn = (SecDbConnectionRef)value;
     if (dbconn->handle) {
-        sqlite3_close(dbconn->handle);
+        int s3e = sqlite3_close(dbconn->handle);
+        if (s3e != SQLITE_OK) {
+            secerror("failed to close database connection (%d) for %@: %s", s3e, dbconn->db->db_path, sqlite3_errmsg(dbconn->handle));
+        }
     }
     dbconn->db = NULL;
     CFReleaseNull(dbconn->changes);
index 8490084d2d27a7ea761bb2d788ded47dcb6f75ee..dd545ec2c1c1296e31c2aad5b2cbc83e9a9c5f61 100644 (file)
@@ -108,41 +108,20 @@ static bool OSX_AddKeyValuePairToKeychainLoggingTransaction(void *token, CFStrin
        msgtracer_msg_t msg = instance->message;
        
        // Fix up the key
-       CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key);
+       __block char *real_key = NULL;
+       CFStringPerformWithCString(key, ^(const char *key_utf8) {
+               asprintf(&real_key, "%s%s", gMessageTracerSetPrefix, key_utf8);
+       });
        if (NULL == real_key)
        {
                return false;
        }
        
-       CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8);
-    key_length += 1; // For null
-    char key_buffer[key_length];
-    memset(key_buffer, 0, key_length);
-    if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8))
-    {
-        CFRelease(real_key);
-        return false;
-    }
-       CFRelease(real_key);
-       
-       CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value);
-    if (NULL == value_str)
-    {
-        return false;
-    }
+       char value_buffer[32];
+       snprintf(value_buffer, sizeof(value_buffer), "%lld", value);
 
-    CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8);
-    value_str_numBytes += 1; // For null
-    char value_buffer[value_str_numBytes];
-    memset(value_buffer, 0, value_str_numBytes);
-    if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8))
-    {
-        CFRelease(value_str);
-        return false;
-    }
-    CFRelease(value_str);
-
-    msgtracer_set(msg, key_buffer, value_buffer);
+       msgtracer_set(msg, real_key, value_buffer);
+       free(real_key);
        return true;    
 }
 
@@ -198,47 +177,23 @@ static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
     }
 
     // Fix up the key
-       CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key);
+       __block char *real_key = NULL;
+       CFStringPerformWithCString(key, ^(const char *key_utf8) {
+               asprintf(&real_key, "%s%s", gMessageTracerSetPrefix, key_utf8);
+       });
        if (NULL == real_key)
        {
                return false;
        }
        
-       CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8);
-    key_length += 1; // For null
-    char key_buffer[key_length];
-    memset(key_buffer, 0,key_length);
-    if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8))
-    {
-        CFRelease(real_key);
-        return false;
-    }
-       CFRelease(real_key);
-       
-       
-       CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value);
-    if (NULL == value_str)
-    {
-        msgtracer_msg_free(message);
-        return result;
-    }
-   
-    CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8);
-    value_str_numBytes += 1; // For null
-    char value_buffer[value_str_numBytes];
-    memset(value_buffer, 0, value_str_numBytes);
-    if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8))
-    {
-        msgtracer_msg_free(message);
-        CFRelease(value_str);
-        return result;
-    }
-    CFRelease(value_str);
+       char value_buffer[32];
+       snprintf(value_buffer, sizeof(value_buffer), "%lld", value);
 
-    msgtracer_set(message, key_buffer, value_buffer);
-       msgtracer_log(message, ASL_LEVEL_NOTICE, "%s is %lld", key_buffer, value);
+    msgtracer_set(message, real_key, value_buffer);
+       msgtracer_log(message, ASL_LEVEL_NOTICE, "%s is %lld", real_key, value);
     msgtracer_msg_free(message);
     msgtracer_domain_free(domain);
+    free(real_key);
        return true;
        
 }
index 9ffdcdaab3b9325f1fcf2bf87e98c8febf7a6930..b4dab54e45809ab8c6f7656eefc59e21b4e07892 100644 (file)
@@ -355,6 +355,7 @@ _SecPKCS12Import
 _SecRandomCopyBytes
 _SecSHA1DigestCreate
 _SecTaskCopySigningIdentifier
+_SecTaskCopyTeamIdentifier
 _SecTaskCopyValueForEntitlement
 _SecTaskCopyValuesForEntitlements
 _SecTaskCreateFromSelf
@@ -1474,6 +1475,7 @@ _SecCodeSetStatus
 _SecCodeCopyStaticCode
 _SecCodeCopyHost
 _SecCodeCopyGuestWithAttributes
+_SecCodeCreateWithAuditToken
 _SecCodeCreateWithPID
 _SecCodeCheckValidity
 _SecCodeCheckValidityWithErrors
@@ -1524,6 +1526,9 @@ _kSecCodeSignerApplicationData
 _kSecCodeSignerDetached
 _kSecCodeSignerDigestAlgorithm
 _kSecCodeSignerDryRun
+_kSecCodeSignerEditCMS
+_kSecCodeSignerEditCpuSubtype
+_kSecCodeSignerEditCpuType
 _kSecCodeSignerEntitlements
 _kSecCodeSignerFlags
 _kSecCodeSignerIdentifier
@@ -1540,12 +1545,17 @@ _kSecCodeSignerTeamIdentifier
 _kSecCodeSignerPlatformIdentifier
 _kSecCodeSignerRuntimeVersion
 _kSecCodeSignerPreserveAFSC
+_kSecCodeSignerOmitAdhocFlag
 _kSecCodeSignerTimestampServer
 _kSecCodeSignerTimestampAuthentication
 _kSecCodeSignerTimestampOmitCertificates
+_kSecCodeInfoCdHashes
+_kSecCodeInfoCdHashesFull
 _kSecCodeInfoCertificates
 _kSecCodeInfoChangedFiles
 _kSecCodeInfoCMS
+_kSecCodeInfoCMSDigest
+_kSecCodeInfoCMSDigestHashType
 _kSecCodeInfoTime
 _kSecCodeInfoTimestamp
 _kSecCodeInfoDesignatedRequirement
@@ -1567,7 +1577,6 @@ _kSecCodeInfoStatus
 _kSecCodeInfoTeamIdentifier
 _kSecCodeInfoTrust
 _kSecCodeInfoUnique
-_kSecCodeInfoCdHashes
 _kSecCodeInfoRuntimeVersion
 _kSecCodeInfoCodeDirectory
 _kSecCodeInfoCodeOffset
@@ -1706,7 +1715,10 @@ _kSecCodeAttributeArchitecture
 _kSecCodeAttributeBundleVersion
 _kSecCodeAttributeSubarchitecture
 _kSecCodeInfoCMS
+_kSecCodeInfoCMSDigest
+_kSecCodeInfoCMSDigestHashType
 _kSecCodeInfoCdHashes
+_kSecCodeInfoCdHashesFull
 _kSecCodeInfoChangedFiles
 _kSecCodeInfoCodeDirectory
 _kSecCodeInfoCodeOffset
index b3e41b60e886842db66447f8bd46e72dcbea787f..0f7c78848645df1d7c02009209d20dcbab67ef6c 100644 (file)
 /* Begin PBXBuildFile section */
                091B39732063B67700ECAB6F /* RemoteServiceDiscovery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 091B396D2063B64A00ECAB6F /* RemoteServiceDiscovery.framework */; };
                0927FEBC1F81338600864E07 /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; };
+               0940F6F82151316500C06F18 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; };
+               0940F6F92151316600C06F18 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; };
                096C647020AB1BC700D7B7D5 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; };
                09A3B9D81F8267BB00C5C324 /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
                09A3B9D91F8267BB00C5C324 /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
                09A3B9E21F838A3400C5C324 /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; };
                09BFE35C20A32E0E008511E9 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; };
                09CB49701F2F64E300C8E4DE /* si-44-seckey-fv.m in Sources */ = {isa = PBXBuildFile; fileRef = 09CB496A1F2F64AF00C8E4DE /* si-44-seckey-fv.m */; };
+               09EF431B21A5A8CC0066CF20 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
                0C0582AE20D9657800D7BD7A /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; };
                0C0582B820D9B70D00D7BD7A /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; };
                0C0BDB32175685B000BC1A7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; };
                0C85DFF61FB38BB6000343A7 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246CE1F9AEAE300D63882 /* libDER.a */; };
                0C85DFF71FB38BB6000343A7 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; };
                0C85DFF81FB38BB6000343A7 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
-               0C85DFF91FB38BB6000343A7 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               0C85DFF91FB38BB6000343A7 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                0C85DFFA1FB38BB6000343A7 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; };
                0C85DFFB1FB38BB6000343A7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; };
                0C85DFFE1FB38BB6000343A7 /* OCMock.framework in Embed OCMock */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
                443381ED18A3D83100215606 /* SecAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381D918A3D81400215606 /* SecAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
                443381EE18A3D83A00215606 /* SecAccessControlPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381DA18A3D81400215606 /* SecAccessControlPriv.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4469FBFF1AA0A4820021AA26 /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDC1AA0A45C0021AA26 /* libctkclient_test.a */; };
-               44A655831AA4B4BB0059D185 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
-               44A655A51AA4B4C70059D185 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
-               44A655A61AA4B4C80059D185 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               44A655831AA4B4BB0059D185 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
+               44A655A51AA4B4C70059D185 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
+               44A655A61AA4B4C80059D185 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                470415DC1E5E1534001F3D95 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 470415DB1E5E1534001F3D95 /* main.m */; };
                470D96711FCDE55B0065FE90 /* SecCDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 470D966F1FCDE55B0065FE90 /* SecCDKeychain.h */; };
                470D96721FCDE55B0065FE90 /* SecCDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 470D966F1FCDE55B0065FE90 /* SecCDKeychain.h */; };
                6C9808571E788AEB00E70590 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
                6C9808581E788AEB00E70590 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; };
                6C9808591E788AEB00E70590 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
-               6C98085A1E788AEB00E70590 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               6C98085A1E788AEB00E70590 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                6C98085B1E788AEB00E70590 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; };
                6C98085C1E788AEB00E70590 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; };
                6C98087A1E788AFD00E70590 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; };
                6C9808931E788AFD00E70590 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
                6C9808941E788AFD00E70590 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; };
                6C9808951E788AFD00E70590 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
-               6C9808961E788AFD00E70590 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               6C9808961E788AFD00E70590 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                6C9808971E788AFD00E70590 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; };
                6C9808981E788AFD00E70590 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; };
                6C9808A51E788CD100E70590 /* CKKSCloudKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */; };
                6C9808A61E788CD200E70590 /* CKKSCloudKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */; };
                6C9AA7A11F7C1D9000D08296 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C9AA7A01F7C1D9000D08296 /* main.m */; };
                6C9AA7A51F7C6F7F00D08296 /* SecArgParse.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5BCC461E5380EA00649140 /* SecArgParse.c */; };
+               6CA837642210CA8A002770F1 /* kc-45-change-password.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CA837612210C5E7002770F1 /* kc-45-change-password.c */; };
                6CAA8CDD1F82EDEF007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; };
                6CAA8CEE1F83E417007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; };
                6CAA8CEF1F83E65D007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; };
                DC1789251D7799CD00B50D50 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789241D7799CD00B50D50 /* CoreFoundation.framework */; };
                DC1789271D7799D400B50D50 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789261D7799D300B50D50 /* IOKit.framework */; };
                DC1789281D779A0F00B50D50 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
-               DC1789291D779A2800B50D50 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               DC1789291D779A2800B50D50 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                DC17892A1D779A3200B50D50 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
                DC1789471D779AAF00B50D50 /* libsecurity_smime.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1784491D77869A00B50D50 /* libsecurity_smime.a */; };
                DC1789A21D779DF400B50D50 /* SecBreadcrumb.c in Sources */ = {isa = PBXBuildFile; fileRef = DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */; };
                DC3502D31E02115200BC0587 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; };
                DC3502D61E02118000BC0587 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; };
                DC3502DF1E02129F00BC0587 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; };
-               DC3502E21E0212D100BC0587 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               DC3502E21E0212D100BC0587 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                DC3502E31E0212E600BC0587 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; };
                DC3502E41E02130600BC0587 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
                DC3502E71E0214C800BC0587 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; };
                DC52EE711D80D85F00B0A59C /* SecECKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E491D8085FC00865A7C /* SecECKey.m */; };
                DC52EE721D80D86400B0A59C /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E9A1D8085FC00865A7C /* SecuritydXPC.c */; };
                DC52EE731D80D86800B0A59C /* SecKey.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E601D8085FC00865A7C /* SecKey.c */; };
-               DC52EE741D80D86F00B0A59C /* SecAccessControl.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E301D8085FC00865A7C /* SecAccessControl.c */; };
+               DC52EE741D80D86F00B0A59C /* SecAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E301D8085FC00865A7C /* SecAccessControl.m */; };
                DC52EE761D80D87F00B0A59C /* SecCTKKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E441D8085FC00865A7C /* SecCTKKey.m */; };
                DC52EE771D80D88300B0A59C /* SecDH.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E461D8085FC00865A7C /* SecDH.c */; };
                DC52EE781D80D88800B0A59C /* SecRSAKey.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E851D8085FC00865A7C /* SecRSAKey.c */; };
                DCC78EE31D808B1300865A7C /* SecCMS.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E421D8085FC00865A7C /* SecCMS.c */; };
                DCC78EE41D808B1B00865A7C /* SecCFAllocator.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E401D8085FC00865A7C /* SecCFAllocator.c */; };
                DCC78EE51D808B2100865A7C /* SecBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E351D8085FC00865A7C /* SecBase64.c */; };
-               DCC78EE61D808B2A00865A7C /* SecAccessControl.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E301D8085FC00865A7C /* SecAccessControl.c */; };
+               DCC78EE61D808B2A00865A7C /* SecAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E301D8085FC00865A7C /* SecAccessControl.m */; };
                DCC78EE71D808B2F00865A7C /* secViewDisplay.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D9E1D8085F200865A7C /* secViewDisplay.c */; };
                DCCA5E841E539EE7009EE93D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCCA5E831E539EE7009EE93D /* AppKit.framework */; };
                DCCBFA1E1DBA95CD001DD54D /* kc-20-item-delete-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = DCCBFA1D1DBA95CD001DD54D /* kc-20-item-delete-stress.c */; };
                DCE4E8121D7A4E4F00AFB96E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789261D7799D300B50D50 /* IOKit.framework */; };
                DCE4E8131D7A4E5300AFB96E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789241D7799CD00B50D50 /* CoreFoundation.framework */; };
                DCE4E81C1D7A4E8F00AFB96E /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E81B1D7A4E8F00AFB96E /* libsqlite3.0.dylib */; };
-               DCE4E81F1D7A4EA700AFB96E /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               DCE4E81F1D7A4EA700AFB96E /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                DCE4E8201D7A4EAC00AFB96E /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
                DCE4E8231D7A4EC900AFB96E /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
                DCE4E8241D7A4ECD00AFB96E /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB2CA4D81D2C28C800AB770F /* libaks.a */; };
                EBCE16501FE6DE5A002E7CCC /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; };
                EBCE16511FE6DE5A002E7CCC /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; };
                EBCE16521FE6DE5A002E7CCC /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; };
-               EBCE16531FE6DE5A002E7CCC /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient.a */; };
+               EBCE16531FE6DE5A002E7CCC /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; };
                EBCE16541FE6DE5A002E7CCC /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; };
                EBCE16551FE6DE5A002E7CCC /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; };
                EBCE16561FE6DE5A002E7CCC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; };
                443381D918A3D81400215606 /* SecAccessControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAccessControl.h; path = ../../../keychain/SecAccessControl.h; sourceTree = "<group>"; };
                443381DA18A3D81400215606 /* SecAccessControlPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAccessControlPriv.h; sourceTree = "<group>"; };
                4469FBDC1AA0A45C0021AA26 /* libctkclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient_test.a; path = usr/local/lib/libctkclient_test.a; sourceTree = SDKROOT; };
-               4469FBDD1AA0A45C0021AA26 /* libctkclient.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient.a; path = usr/local/lib/libctkclient.a; sourceTree = SDKROOT; };
+               4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient_sep.a; path = usr/local/lib/libctkclient_sep.a; sourceTree = SDKROOT; };
                470415CF1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = seckeychainnetworkextensionstest; sourceTree = BUILT_PRODUCTS_DIR; };
                470415DB1E5E1534001F3D95 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RegressionTests/seckeychainnetworkextensionstest/main.m; sourceTree = SOURCE_ROOT; };
                470415DD1E5E15B3001F3D95 /* seckeychainnetworkextensionstest.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; name = seckeychainnetworkextensionstest.entitlements; path = RegressionTests/seckeychainnetworkextensionstest/seckeychainnetworkextensionstest.entitlements; sourceTree = SOURCE_ROOT; };
                6C9AA79E1F7C1D8F00D08296 /* supdctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = supdctl; sourceTree = BUILT_PRODUCTS_DIR; };
                6C9AA7A01F7C1D9000D08296 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
                6CA2B9431E9F9F5700C43444 /* RateLimiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RateLimiter.h; sourceTree = "<group>"; };
+               6CA557FE219E214200993CF4 /* securityuploadd-sim.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "securityuploadd-sim.plist"; sourceTree = "<group>"; };
+               6CA837612210C5E7002770F1 /* kc-45-change-password.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "kc-45-change-password.c"; path = "regressions/kc-45-change-password.c"; sourceTree = "<group>"; };
                6CAA8D201F842FB3007B6E03 /* securityuploadd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securityuploadd; sourceTree = BUILT_PRODUCTS_DIR; };
                6CB5F4751E4025AB00DBF3F0 /* CKKSCloudKitTestsInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = CKKSCloudKitTestsInfo.plist; sourceTree = "<group>"; };
                6CB5F4781E402E5700DBF3F0 /* KeychainCKKS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = KeychainCKKS.plist; path = testrunner/KeychainCKKS.plist; sourceTree = "<group>"; };
                DC3A4B581D91E9FB00E46D4A /* com.apple.CodeSigningHelper.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = com.apple.CodeSigningHelper.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
                DC3A4B5F1D91EAC500E46D4A /* CodeSigningHelper-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "CodeSigningHelper-Info.plist"; sourceTree = "<group>"; };
                DC3A4B601D91EAC500E46D4A /* com.apple.CodeSigningHelper.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.CodeSigningHelper.sb; sourceTree = "<group>"; };
-               DC3A4B621D91EAC500E46D4A /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+               DC3A4B621D91EAC500E46D4A /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; usesTabs = 1; };
                DC3A81D41D99D567000C7419 /* libcoretls_cfhelpers.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcoretls_cfhelpers.dylib; path = usr/lib/libcoretls_cfhelpers.dylib; sourceTree = SDKROOT; };
                DC3D748A1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSLocalSynchronizeOperation.h; sourceTree = "<group>"; };
                DC3D748B1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLocalSynchronizeOperation.m; sourceTree = "<group>"; };
                DC5ABF7F1D83511A00CF422C /* key.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
                DC5ABF801D83511A00CF422C /* key.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = key.cpp; sourceTree = "<group>"; };
                DC5ABF811D83511A00CF422C /* process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = "<group>"; };
-               DC5ABF821D83511A00CF422C /* process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = process.cpp; sourceTree = "<group>"; };
+               DC5ABF821D83511A00CF422C /* process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = process.cpp; sourceTree = "<group>"; usesTabs = 1; };
                DC5ABF831D83511A00CF422C /* server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = "<group>"; };
                DC5ABF841D83511A00CF422C /* server.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = server.cpp; sourceTree = "<group>"; };
                DC5ABF851D83511A00CF422C /* session.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = "<group>"; };
                DC5ABFB91D83511A00CF422C /* authhost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = authhost.cpp; sourceTree = "<group>"; };
                DC5ABFBA1D83511A00CF422C /* credential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = credential.h; sourceTree = "<group>"; };
                DC5ABFBB1D83511A00CF422C /* credential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = credential.cpp; sourceTree = "<group>"; };
-               DC5ABFBD1D83511A00CF422C /* clientid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clientid.h; sourceTree = "<group>"; };
+               DC5ABFBD1D83511A00CF422C /* clientid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clientid.h; sourceTree = "<group>"; usesTabs = 1; };
                DC5ABFBE1D83511A00CF422C /* clientid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clientid.cpp; sourceTree = "<group>"; };
                DC5ABFBF1D83511A00CF422C /* codesigdb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = codesigdb.h; sourceTree = "<group>"; };
                DC5ABFC01D83511A00CF422C /* codesigdb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = codesigdb.cpp; sourceTree = "<group>"; };
                DCC78E2A1D8085FC00865A7C /* p12import.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12import.c; sourceTree = "<group>"; };
                DCC78E2C1D8085FC00865A7C /* p12pbegen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12pbegen.c; sourceTree = "<group>"; };
                DCC78E2E1D8085FC00865A7C /* pbkdf2.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pbkdf2.c; sourceTree = "<group>"; };
-               DCC78E301D8085FC00865A7C /* SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAccessControl.c; sourceTree = "<group>"; };
+               DCC78E301D8085FC00865A7C /* SecAccessControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecAccessControl.m; sourceTree = "<group>"; };
                DCC78E321D8085FC00865A7C /* SecAccessControlExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecAccessControlExports.exp-in"; sourceTree = "<group>"; };
                DCC78E351D8085FC00865A7C /* SecBase64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase64.c; sourceTree = "<group>"; };
                DCC78E381D8085FC00865A7C /* SecCertificate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificate.c; sourceTree = "<group>"; };
                DCD067DF1D8CDF7E007602F1 /* singlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = singlediskrep.cpp; sourceTree = "<group>"; };
                DCD067E01D8CDF7E007602F1 /* detachedrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detachedrep.h; sourceTree = "<group>"; };
                DCD067E11D8CDF7E007602F1 /* detachedrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detachedrep.cpp; sourceTree = "<group>"; };
-               DCD067E21D8CDF7E007602F1 /* piddiskrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piddiskrep.h; sourceTree = "<group>"; };
-               DCD067E31D8CDF7E007602F1 /* piddiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = piddiskrep.cpp; sourceTree = "<group>"; };
+               DCD067E21D8CDF7E007602F1 /* piddiskrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piddiskrep.h; sourceTree = "<group>"; usesTabs = 0; };
+               DCD067E31D8CDF7E007602F1 /* piddiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = piddiskrep.cpp; sourceTree = "<group>"; usesTabs = 1; };
                DCD067E71D8CDF7E007602F1 /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodeHostLib.h; sourceTree = "<group>"; };
                DCD067E81D8CDF7E007602F1 /* SecCodeHostLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCodeHostLib.c; sourceTree = "<group>"; };
                DCD067EA1D8CDF7E007602F1 /* sp-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "sp-watch.d"; path = "../dtrace/sp-watch.d"; sourceTree = "<group>"; };
                F6A0971F1E953ABD00B1E7D6 /* authdtests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = authdtests.m; path = OSX/authd/tests/authdtests.m; sourceTree = "<group>"; };
                F6A3CB0D1E7062BA00E7821F /* authd-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "authd-Entitlements.plist"; path = "OSX/authd/authd-Entitlements.plist"; sourceTree = "<group>"; };
                F93C493A1AB8FF530047E01A /* ckcdiagnose.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ckcdiagnose.sh; sourceTree = "<group>"; };
+               F9B458272183E01100F6BCEB /* SignatureEditing.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = SignatureEditing.sh; path = OSX/codesign_tests/SignatureEditing.sh; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                0C85DFF71FB38BB6000343A7 /* libbsm.dylib in Frameworks */,
                                D491116E209559510066A1E4 /* CoreData.framework in Frameworks */,
                                0C85DFF81FB38BB6000343A7 /* libcoreauthd_client.a in Frameworks */,
-                               0C85DFF91FB38BB6000343A7 /* libctkclient.a in Frameworks */,
+                               0C85DFF91FB38BB6000343A7 /* libctkclient_sep.a in Frameworks */,
                                0C85DFFA1FB38BB6000343A7 /* libsqlite3.0.dylib in Frameworks */,
                                0C85DFFB1FB38BB6000343A7 /* libz.dylib in Frameworks */,
                        );
                                0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */,
                                D46246971F9AE2E400D63882 /* libDER.a in Frameworks */,
                                DCD22D771D8CC9CD001C9B81 /* libASN1_not_installed.a in Frameworks */,
-                               44A655831AA4B4BB0059D185 /* libctkclient.a in Frameworks */,
+                               44A655831AA4B4BB0059D185 /* libctkclient_sep.a in Frameworks */,
                                DC59E9A41D91C6F0001BDDF5 /* libCMS.a in Frameworks */,
                                DCD22D781D8CC9D8001C9B81 /* libsecurity_ssl.a in Frameworks */,
                                CD791B3D1DFC9AB200F0E5DC /* libsqlite3.dylib in Frameworks */,
                                4432AF8D1A01472C000958DC /* libaks_acl.a in Frameworks */,
                                438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */,
                                4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */,
+                               0940F6F82151316500C06F18 /* libACM.a in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                DCD22D9C1D8CCFD6001C9B81 /* libutilitiesRegressions.a in Frameworks */,
                                DC00ABB71D821E2F00513D74 /* libiOSSecurityRegressions.a in Frameworks */,
                                DC00ABB81D821E3300513D74 /* libiOSsecuritydRegressions.a in Frameworks */,
-                               44A655A61AA4B4C80059D185 /* libctkclient.a in Frameworks */,
+                               44A655A61AA4B4C80059D185 /* libctkclient_sep.a in Frameworks */,
                                DC00ABB91D821E3A00513D74 /* libSOSRegressions.a in Frameworks */,
                                4C711D6C13AFCD0900FE865D /* libsqlite3.dylib in Frameworks */,
                                BE405EE31DC2F11E00E227B1 /* libz.dylib in Frameworks */,
                                6C9808571E788AEB00E70590 /* libaks_acl.a in Frameworks */,
                                6C9808581E788AEB00E70590 /* libbsm.dylib in Frameworks */,
                                6C9808591E788AEB00E70590 /* libcoreauthd_client.a in Frameworks */,
-                               6C98085A1E788AEB00E70590 /* libctkclient.a in Frameworks */,
+                               6C98085A1E788AEB00E70590 /* libctkclient_sep.a in Frameworks */,
                                6C98085B1E788AEB00E70590 /* libsqlite3.0.dylib in Frameworks */,
                                6C98085C1E788AEB00E70590 /* libz.dylib in Frameworks */,
                        );
                                6C9808931E788AFD00E70590 /* libaks_acl.a in Frameworks */,
                                6C9808941E788AFD00E70590 /* libbsm.dylib in Frameworks */,
                                6C9808951E788AFD00E70590 /* libcoreauthd_client.a in Frameworks */,
-                               6C9808961E788AFD00E70590 /* libctkclient.a in Frameworks */,
+                               6C9808961E788AFD00E70590 /* libctkclient_sep.a in Frameworks */,
                                6C9808971E788AFD00E70590 /* libsqlite3.0.dylib in Frameworks */,
                                6C9808981E788AFD00E70590 /* libz.dylib in Frameworks */,
                        );
                                DC17892A1D779A3200B50D50 /* libcoreauthd_client.a in Frameworks */,
                                DC3A81D61D99D57F000C7419 /* libcoretls.dylib in Frameworks */,
                                DC3A81D71D99D58A000C7419 /* libcoretls_cfhelpers.dylib in Frameworks */,
-                               DC1789291D779A2800B50D50 /* libctkclient.a in Frameworks */,
+                               DC1789291D779A2800B50D50 /* libctkclient_sep.a in Frameworks */,
                                D46246C91F9AEA5300D63882 /* libDER.a in Frameworks */,
                                DC17891D1D77999700B50D50 /* libpam.dylib in Frameworks */,
                                DC17891F1D77999D00B50D50 /* libsqlite3.dylib in Frameworks */,
                                DC1789231D7799A600B50D50 /* libz.dylib in Frameworks */,
                                DC1789251D7799CD00B50D50 /* CoreFoundation.framework in Frameworks */,
                                DC1789271D7799D400B50D50 /* IOKit.framework in Frameworks */,
+                               0940F6F92151316600C06F18 /* libACM.a in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                DC0950411E38271300B2C8AC /* libaks_acl.a in Frameworks */,
                                DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */,
                                DC3502E41E02130600BC0587 /* libcoreauthd_client.a in Frameworks */,
-                               DC3502E21E0212D100BC0587 /* libctkclient.a in Frameworks */,
+                               DC3502E21E0212D100BC0587 /* libctkclient_sep.a in Frameworks */,
                                DC3502CA1E020DC100BC0587 /* libsqlite3.0.dylib in Frameworks */,
                                DC222C321E0240D300B09171 /* libz.dylib in Frameworks */,
                        );
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               09EF431B21A5A8CC0066CF20 /* libaks_acl.a in Frameworks */,
                                D4C6C5CD1FB3B423007EA57E /* libarchive.tbd in Frameworks */,
                                D46246B71F9AE76500D63882 /* libDER.a in Frameworks */,
                                DC3A81EC1D99F568000C7419 /* libcoretls.dylib in Frameworks */,
                                DCE4E8231D7A4EC900AFB96E /* libaks_acl.a in Frameworks */,
                                DCD22D711D8CC78E001C9B81 /* libASN1_not_installed.a in Frameworks */,
                                DCE4E8201D7A4EAC00AFB96E /* libcoreauthd_client.a in Frameworks */,
-                               DCE4E81F1D7A4EA700AFB96E /* libctkclient.a in Frameworks */,
+                               DCE4E81F1D7A4EA700AFB96E /* libctkclient_sep.a in Frameworks */,
                                DCE4E81C1D7A4E8F00AFB96E /* libsqlite3.0.dylib in Frameworks */,
                                DCD8A2041E09FB0D00E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */,
                                DC00AB7A1D821C6B00513D74 /* libSecureObjectSyncServer.a in Frameworks */,
                                DCD22D951D8CCE5E001C9B81 /* libutilitiesRegressions.a in Frameworks */,
                                DC00ABC41D821ED900513D74 /* libiOSSecurityRegressions.a in Frameworks */,
                                DC00ABC51D821EDC00513D74 /* libiOSsecuritydRegressions.a in Frameworks */,
-                               44A655A51AA4B4C70059D185 /* libctkclient.a in Frameworks */,
+                               44A655A51AA4B4C70059D185 /* libctkclient_sep.a in Frameworks */,
                                DC00ABC61D821EE500513D74 /* libSOSRegressions.a in Frameworks */,
                                4432B1601A014D85000958DC /* libcoreauthd_client.a in Frameworks */,
                                4432B1611A014D85000958DC /* libaks_acl.a in Frameworks */,
                                EBCE16501FE6DE5A002E7CCC /* libaks_acl.a in Frameworks */,
                                EBCE16511FE6DE5A002E7CCC /* libbsm.dylib in Frameworks */,
                                EBCE16521FE6DE5A002E7CCC /* libcoreauthd_client.a in Frameworks */,
-                               EBCE16531FE6DE5A002E7CCC /* libctkclient.a in Frameworks */,
+                               EBCE16531FE6DE5A002E7CCC /* libctkclient_sep.a in Frameworks */,
                                EBCE16541FE6DE5A002E7CCC /* libprequelite.tbd in Frameworks */,
                                EBCE16551FE6DE5A002E7CCC /* libsqlite3.0.dylib in Frameworks */,
                                D4911171209559620066A1E4 /* CoreData.framework in Frameworks */,
                                4432AF6A1A01458F000958DC /* libcoreauthd_client.a */,
                                5E8B53A41AA0B8A600345E7B /* libcoreauthd_test_client.a */,
                                E7AAB5F415929493005C8BCC /* libcorecrypto.dylib */,
-                               4469FBDD1AA0A45C0021AA26 /* libctkclient.a */,
+                               4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */,
                                4469FBDC1AA0A45C0021AA26 /* libctkclient_test.a */,
                                4CB740680A4749C800D641BB /* libsqlite3.dylib */,
                        );
                        children = (
                                DCC78E281D8085FC00865A7C /* AppleBaselineEscrowCertificates.h */,
                                D41149A01E7C935D00C078C7 /* AppleiPhoneDeviceCACertificates.h */,
-                               DCC78E301D8085FC00865A7C /* SecAccessControl.c */,
+                               DCC78E301D8085FC00865A7C /* SecAccessControl.m */,
                                443381D918A3D81400215606 /* SecAccessControl.h */,
                                443381DA18A3D81400215606 /* SecAccessControlPriv.h */,
                                DCC78E351D8085FC00865A7C /* SecBase64.c */,
                        isa = PBXGroup;
                        children = (
                                DC610A671D78FA76002223DE /* teamid.sh */,
+                               F9B458272183E01100F6BCEB /* SignatureEditing.sh */,
                                DC610A631D78FA54002223DE /* CaspianTests */,
                                DC610A641D78FA54002223DE /* LocalCaspianTestRun.sh */,
                                DC610A681D78FA87002223DE /* validation.sh */,
                                DCB3446D1D8A35270054D16E /* kc-43-seckey-interop.m */,
                                DCB3446E1D8A35270054D16E /* kc-42-trust-revocation.c */,
                                24CBF8731E9D4E4500F09F0E /* kc-44-secrecoverypassword.c */,
+                               6CA837612210C5E7002770F1 /* kc-45-change-password.c */,
                                DCB3446F1D8A35270054D16E /* si-20-sectrust-provisioning.c */,
                                DCB344701D8A35270054D16E /* si-20-sectrust-provisioning.h */,
                                DCB344711D8A35270054D16E /* si-33-keychain-backup.c */,
                                09A3B9E21F838A3400C5C324 /* SecKeyProxy.m in Sources */,
                                DC52EE771D80D88300B0A59C /* SecDH.c in Sources */,
                                DC52EE761D80D87F00B0A59C /* SecCTKKey.m in Sources */,
-                               DC52EE741D80D86F00B0A59C /* SecAccessControl.c in Sources */,
+                               DC52EE741D80D86F00B0A59C /* SecAccessControl.m in Sources */,
                                DC52EE731D80D86800B0A59C /* SecKey.c in Sources */,
                                DC52EE721D80D86400B0A59C /* SecuritydXPC.c in Sources */,
                                DC52EE711D80D85F00B0A59C /* SecECKey.m in Sources */,
                                DCB344971D8A35270054D16E /* kc-26-key-import-public.m in Sources */,
                                DCB344981D8A35270054D16E /* kc-27-key-non-extractable.c in Sources */,
                                DCB3449A1D8A35270054D16E /* kc-28-cert-sign.c in Sources */,
+                               6CA837642210CA8A002770F1 /* kc-45-change-password.c in Sources */,
                                DCB344991D8A35270054D16E /* kc-28-p12-import.m in Sources */,
                                DCB3449B1D8A35270054D16E /* kc-30-xara.c in Sources */,
                                DCB344A01D8A35270054D16E /* kc-40-seckey.m in Sources */,
                                0CAD1E581E1C5C6C00537693 /* SOSCloudCircle.m in Sources */,
                                DC5B391A20C08B70005B09F6 /* SecBase.c in Sources */,
                                DCC78EE71D808B2F00865A7C /* secViewDisplay.c in Sources */,
-                               DCC78EE61D808B2A00865A7C /* SecAccessControl.c in Sources */,
+                               DCC78EE61D808B2A00865A7C /* SecAccessControl.m in Sources */,
                                DCC78EE51D808B2100865A7C /* SecBase64.c in Sources */,
                                DCC78EE41D808B1B00865A7C /* SecCFAllocator.c in Sources */,
                                DCC78EE31D808B1300865A7C /* SecCMS.c in Sources */,
index dc5def770c1173b74b7ceebed198513dc5a4acbe..a44c8e8ea840b8eca3d968e82ca7b42461c4ccc6 100644 (file)
@@ -10,6 +10,8 @@
        <true/>
        <key>com.apple.keystore.access-keychain-keys</key>
        <true/>
+       <key>com.apple.keystore.sik.access</key>
+       <true/>
        <key>com.apple.keystore.lockassertion</key>
        <true/>
        <key>com.apple.keystore.device</key>
index 188619f0b5a4d0d582da7a53a8a2c94b1db59e15..608e577cdb9d0a5d7ee64e601f3c1a0eb85fe777 100644 (file)
@@ -37,6 +37,7 @@
 #include <Security/SecKeychainSearch.h>
 #include <Security/SecIdentitySearch.h>
 #include <Security/SecKey.h>
+#include <Security/SecKeyPriv.h>
 #include <Security/SecCertificate.h>
 #include <Security/SecCertificatePriv.h>
 #include <Security/SecItem.h>
@@ -559,7 +560,7 @@ ctk_obj_to_str(CFTypeRef obj, char *buf, int bufLen, Boolean key)
 
 typedef struct {
     int i;
-    const char *name;
+    NSString *name;
 } ctk_print_context;
 
 OSStatus
@@ -581,7 +582,7 @@ static void
 ctk_dump_item_header(ctk_print_context *ctx)
 {
     printf("\n");
-    printf("==== %s #%d\n", ctx->name, ctx->i);
+    printf("==== %s #%d\n", ctx->name.UTF8String, ctx->i);
 }
 
 static void
@@ -610,7 +611,7 @@ ctk_dump_item(CFTypeRef item, ctk_print_context *ctx)
 }
 
 static OSStatus
-ctk_dump_items(CFArrayRef items, CFTypeRef secClass, const char *name)
+ctk_dump_items(CFArrayRef items, id secClass, NSString *name)
 {
     OSStatus stat = errSecSuccess;
 
@@ -629,17 +630,33 @@ ctk_dump_items(CFArrayRef items, CFTypeRef secClass, const char *name)
     return stat;
 }
 
+static void
+exportData(NSData *dataToExport, NSString *fileName, NSString *exportPath, NSString *elementName) {
+    NSMutableString *pem = [NSMutableString new];
+    [pem appendString:[NSString stringWithFormat:@"-----BEGIN %@-----\n", elementName]];
+    NSString *base64Cert = [dataToExport base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed];
+    [pem appendString:base64Cert];
+    [pem appendString:[NSString stringWithFormat:@"\n-----END %@-----\n", elementName]];
+    
+    NSString *fullName = [NSString stringWithFormat:@"%@/%@.pem", exportPath, fileName];
+    NSError *error;
+    [pem writeToFile:fullName atomically:YES encoding:NSUTF8StringEncoding error:&error];
+    if (error) {
+        fprintf(stderr, "%s\n", [NSString stringWithFormat:@"%@", error].UTF8String);
+    }
+}
+
 static OSStatus
-ctk_dump(CFTypeRef secClass, const char *name, const char *tid)
+ctk_dump(id secClass, NSString *name, NSString *tid, NSString *exportPath)
 {
     NSArray *result;
     BOOL returnRef = NO;
 
-    if ([(__bridge id)secClass isEqual:(id)kSecClassIdentity] || [(__bridge id)secClass isEqual:(id)kSecClassCertificate])
+    if ([secClass isEqual:(id)kSecClassIdentity] || [secClass isEqual:(id)kSecClassCertificate])
         returnRef = YES;
 
     NSDictionary *query = @{
-        (id)kSecClass : (__bridge id)secClass,
+        (id)kSecClass : secClass,
         (id)kSecMatchLimit : (id)kSecMatchLimitAll,
         (id)kSecAttrAccessGroup : (id)kSecAttrAccessGroupToken,
         (id)kSecReturnAttributes : @YES,
@@ -648,7 +665,7 @@ ctk_dump(CFTypeRef secClass, const char *name, const char *tid)
 
     if(tid) {
         NSMutableDictionary *updatedQuery = [NSMutableDictionary dictionaryWithDictionary:query];
-        updatedQuery[(id)kSecAttrTokenID] = [NSString stringWithUTF8String:tid];
+        updatedQuery[(id)kSecAttrTokenID] = tid;
         query = updatedQuery;
     }
 
@@ -669,7 +686,7 @@ ctk_dump(CFTypeRef secClass, const char *name, const char *tid)
             for (NSDictionary *dict in result) {
                 NSMutableDictionary *updatedItem = [NSMutableDictionary dictionaryWithDictionary:dict];
                 id itemRef = updatedItem[(id)kSecValueRef];
-                if ([(__bridge id)secClass isEqual:(id)kSecClassIdentity]) {
+                if ([secClass isEqual:(id)kSecClassIdentity]) {
                     id certificateRef;
                     if (SecIdentityCopyCertificate((__bridge SecIdentityRef)itemRef, (void *)&certificateRef) != errSecSuccess)
                         continue;
@@ -680,11 +697,21 @@ ctk_dump(CFTypeRef secClass, const char *name, const char *tid)
                 updatedItem[@"sha1"] = certDigest;
                 [updatedItem removeObjectForKey:(id)kSecValueRef];
                 [updatedResult addObject:updatedItem];
+                
+                if (exportPath) {
+                    NSData *certData = (__bridge_transfer NSData *)SecCertificateCopyData((__bridge SecCertificateRef)itemRef);
+                    exportData(certData, updatedItem[(id)kSecAttrLabel], exportPath, @"CERTIFICATE");
+                    id publicKey = (__bridge_transfer id)SecCertificateCopyKey((__bridge SecCertificateRef)itemRef);
+                    NSData *pubKeyInfo = (__bridge_transfer NSData *)SecKeyCopySubjectPublicKeyInfo((__bridge SecKeyRef)publicKey);
+                    exportData(pubKeyInfo, [NSString stringWithFormat:@"Public Key - %@", updatedItem[(id)kSecAttrLabel]], exportPath, @"PUBLIC KEY");
+                }
             }
             result = updatedResult;
         }
 
-        stat = ctk_dump_items((__bridge CFArrayRef)result, secClass, name);
+        if (!exportPath) {
+            stat = ctk_dump_items((__bridge CFArrayRef)result, secClass, name);
+        }
     } else {
         stat = errSecInternalComponent;
     }
@@ -694,13 +721,16 @@ ctk_dump(CFTypeRef secClass, const char *name, const char *tid)
 int
 ctk_export(int argc, char * const *argv)
 {
-    OSStatus stat = errSecSuccess;
+    __block OSStatus stat = errSecSuccess;
 
     ItemSpec itemSpec = IS_All;
-    const char *tid = NULL;
+    NSString *tid;
+    NSString *exportPath;
     int ch;
+    BOOL optT = NO;
+    BOOL optE = NO;
 
-    while ((ch = getopt(argc, argv, "i:t:h")) != -1) {
+    while ((ch = getopt(argc, argv, "i:t:e:h")) != -1) {
         switch  (ch) {
             case 't':
                 if(!strcmp("certs", optarg)) {
@@ -718,9 +748,15 @@ ctk_export(int argc, char * const *argv)
                 else {
                     return SHOW_USAGE_MESSAGE;
                 }
+                optT = YES;
                 break;
             case 'i':
-                tid = optarg;
+                tid = [NSString stringWithUTF8String:optarg];
+                break;
+            case 'e':
+                exportPath = [NSString stringWithUTF8String:optarg];
+                itemSpec = IS_Certs;
+                optE = YES;
                 break;
 
             case '?':
@@ -728,19 +764,23 @@ ctk_export(int argc, char * const *argv)
                 return SHOW_USAGE_MESSAGE;
         }
     }
+    
+    if (optT && optE) {
+        return SHOW_USAGE_MESSAGE;
+    }
 
-    CFTypeRef classes[] = { kSecClassCertificate, kSecClassKey, kSecClassIdentity };
-    const char* names[] = { "certificate", "private key", "identity" };
-    ItemSpec specs[] = { IS_Certs, IS_PrivKeys, IS_Identities };
-
-    for(size_t i = 0; i < sizeof(classes)/sizeof(classes[0]); i++) {
-        if(specs[i] == itemSpec || itemSpec == IS_All) {
-            stat = ctk_dump(classes[i], names[i], tid);
+    NSDictionary<id, NSArray *> *classesAndNames = @{ (id)kSecClassCertificate : @[ @"certificate", @(IS_Certs) ],
+                                                      (id)kSecClassKey : @[ @"private key", @(IS_PrivKeys) ],
+                                                      (id)kSecClassIdentity : @[ @"identity", @(IS_Identities) ] };
+    
+    [classesAndNames enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) {
+        if (itemSpec == IS_All || itemSpec == ((NSNumber *)obj[1]).unsignedIntegerValue) {
+            stat = ctk_dump(key, obj[0], tid, exportPath);
             if(stat) {
-                break;
+                *stop = YES;
             }
         }
-    }
+    }];
 
     return stat;
 }
index dcbca48fd169f87bda1cb7d5366da4e4c24d0f75..1adbdfcd489f05400b80b43ab516fa7478eae95c 100644 (file)
@@ -128,10 +128,7 @@ do_keychain_set_password(const char *keychainName, const char* oldPassword, cons
                goto cleanup;
        }
 
-       /* lock keychain first to remove existing credentials */
-       (void)SecKeychainLock(keychain);
-
-       /* change the password */
+       /* change the password, if daemon agrees everything looks good */
        result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass);
        if (result)
        {
index a949890f5a256f8b4283c2ce4a727f183028e3d9..bf391cd99e81ecbc23c2ea2298a57b1ad29a47e0 100644 (file)
@@ -190,7 +190,7 @@ Enable, disable or list disabled smartcard tokens.
 .It Nm list-smartcards
 Display available smartcards.
 .It Nm export-smartcard
-Export items from a smartcard.
+Export/display items from a smartcard.
 .It Nm error
 Display a descriptive message for the given error code(s).
 .El
@@ -1611,23 +1611,28 @@ s of available smartcards.
 .Ar token
 .Op Fl i Ar id
 .Op Fl t Ar certs Ns | Ns Ar privKeys Ns | Ns Ar identities Ns | Ns Ar all
+.Op Fl e Ar exportPath
 .Bl -item -offset -indent
-Export items from a smartcard. If
+Export/display items from a smartcard. If
 .Ar id
-isn't provided, items from all smartcards will be exported.
+isn't provided, items from all smartcards will be displayed.
 .It
 Options:
 .Bl -tag -compact -width -indent-indent
 .It Fl i Ar id
-Export items from token specified by token
+Export/display items from token specified by token
 .Ar id Ns
 , available
 .Ar id Ns
 s can be listed by list-smartcards command.
 .It Fl t Ar certs Ns | Ns Ar privKeys Ns | Ns Ar identities Ns | Ns Ar all
-Export items of the specified type (Default:
+Display items of the specified type (Default:
 .Ar all Ns
 )
+.It Fl e Ar exportPath
+Specify path to export certificates and public keys. If
+.Ar exportPath Ns
+ is specified screen output is suppressed. This option cannot be combined with -t option.
 .El
 .El
 .It
index a267dac1cb02b6e3ddccb434e6288021fb83ba92..301f00b5d39f0e05b1fd83662988762be2ea6510 100644 (file)
@@ -505,10 +505,11 @@ const command commands[] =
          "Import items into a keychain." },
 
     { "export-smartcard" , ctk_export,
-        "[-i id] [-t type] \n"
+        "[-i id] [-t type] [-e exportPath] \n"
         "    -i  id of the smartcard to export (available IDs can be listed by list-smartcards\n"
-        "        command, default: export all smartcards)\n"
-        "    -t  Type = certs|privKeys|identities|all  (Default: all)\n",
+        "        command, default: export/display all smartcards)\n"
+        "    -t  Type = certs|privKeys|identities|all  (Default: all)\n"
+        "    -e  Specify path to export certificates and public keys. This option cannot be combined with -t option.\n",
         "Export items from a smartcard." },
 
        { "cms", cms_util,
index 293b43055a3858625f484fd8723d1b98349d3182..456174f96dbcd41d07772fc32bafe456f135642d 100644 (file)
@@ -1190,6 +1190,8 @@ typedef struct {
 #define kSystemKeychainDir             "/Library/Keychains/"
 #define kSystemUnlockFile              "/var/db/SystemKey"
 
+#define kSystemKeychainPath    kSystemKeychainDir kSystemKeychainName
+
 /*
  * CSSM ACL tags used to store partition/integrity data in ACLs
  */
index e444b51fec926b0c099e87bd38672534516918b5..ff0b92861ff06c96ffc1a2924e2ea90f30bea44b 100644 (file)
@@ -879,7 +879,7 @@ SecCDKeychainLookupValueType* const SecCDKeychainLookupValueTypeDate = (SecCDKey
     managedItem.metadata = attributeData;
 
     SecCDKeychainManagedAccessControlEntity* owner = [NSEntityDescription insertNewObjectForEntityForName:SecCDKeychainEntityTypeAccessControlEntity inManagedObjectContext:managedObjectContext];
-    owner.type = item.owner.entityType;
+    owner.type = (int32_t)item.owner.entityType;
     owner.stringRepresentation = item.owner.stringRepresentation;
     managedItem.owner = owner;
     [owner addOwnedItemsObject:managedItem];
index ad370e53b0b9bac485d946d58736b42e012dd06c..ba571b1b591b2a8fee2e2bd158cfa05fa0fb523f 100644 (file)
@@ -778,7 +778,7 @@ extern const CFStringRef kSecAttrKeyClassSymmetric
     @constant kSecAttrKeyTypeRC4 (OSX only)
     @constant kSecAttrKeyTypeRC2 (OSX only)
     @constant kSecAttrKeyTypeCAST (OSX only)
-    @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeEC instead.) (OSX only)
+    @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeECSECPrimeRandom instead.) (OSX only)
 */
 extern const CFStringRef kSecAttrKeyTypeRSA
     API_AVAILABLE(macos(10.7), ios(2.0));
index 0476998d28b8701d7c2c7ceea91298287831bc96..631491fb5db58ee26cd50a7ee84ccc578182829a 100644 (file)
@@ -368,6 +368,7 @@ extern const CFStringRef kSecAttrViewHintAutoUnlock;
 extern const CFStringRef kSecAttrViewHintHealth;
 extern const CFStringRef kSecAttrViewHintApplePay;
 extern const CFStringRef kSecAttrViewHintHome;
+extern const CFStringRef kSecAttrViewHintLimitedPeersAllowed;
 
 
 extern const CFStringRef kSecUseSystemKeychain
index 85467aa661fb463514bb187583f40ced07276302..e5f4c624b3c1398b22a0bc60579094f4eabfe151 100644 (file)
@@ -1076,128 +1076,118 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV
     @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA224AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA384AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA512AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA256AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA224AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA256AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA384AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM
     Legacy ECIES encryption or decryption, use kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA512AESGCM in new code.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG and
-    all-zero 16 byte long IV (initialization vector).
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG and all-zero 16 byte long IV (initialization vector).
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA224AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA384AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA512AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA224AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA256AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA384AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA512AESGCM
     ECIES encryption or decryption.  This algorithm does not limit the size of the message to be encrypted or decrypted.
     Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512.  AES Key size
-    is 128bit for EC keys <=256bit and 256bit for bigger EC keys.  Ephemeral public key data is used as sharedInfo for KDF,
-    and static public key data is used as authenticationData for AES-GCM processing.  AES-GCM uses 16 bytes long TAG, AES key
-    is first half of KDF output and 16 byte long IV (initialization vector) is second half of KDF output.
+    is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF.
+    AES-GCM uses 16 bytes long TAG, AES key is first half of KDF output and 16 byte long IV (initialization vector) is second half
+    of KDF output.
 
     @constant kSecKeyAlgorithmECDHKeyExchangeCofactor
     Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys.
index 0c61b2cfba7adc8c115d0d4c0951bbf5eb3413ce..2507bc2edb6d015f58f0fba16ed15eb1de8996a7 100644 (file)
@@ -347,7 +347,7 @@ enum {
  @result An algorithm identifier.
  */
 CFIndex SecKeyGetAlgorithmId(SecKeyRef key)
-API_AVAILABLE(macos(10.8), ios(9.0));
+SPI_AVAILABLE(macos(10.8), ios(9.0));
 
 #if TARGET_OS_IPHONE
 /*!
@@ -708,6 +708,88 @@ OSStatus SecKeyRawVerifyOSX(
 
 #endif // SEC_OS_OSX_INCLUDES
 
+/*!
+ @constant kSecKeyApplePayEnabled If set to kCFBooleanTrue during SecKeyCreateRandomKey, then the SEP-based key is ApplePay-enabled,
+ which means that it can be used for ECIES to re-crypt.
+ */
+extern const CFStringRef kSecKeyApplePayEnabled
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @constant kSecKeyEncryptionParameterSymmetricKeySizeInBits CFNumberRef with size in bits for ephemeral
+ symmetric key used for encryption/decryption.
+ */
+extern const CFStringRef kSecKeyEncryptionParameterSymmetricKeySizeInBits
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @constant kSecKeyEncryptionParameterSymmetricAAD CFDataRef with additional authentiction data for AES-GCM encryption.
+ */
+extern const CFStringRef kSecKeyEncryptionParameterSymmetricAAD
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @constant kSecKeyEncryptionParameterRecryptParameters Usable only for SecKeyCreateDecryptedDataWithParameters.
+ Contains dictionary with parameters for re-encryption using the same algorithm and encryption parameters
+ specified inside this dictionary.
+ */
+extern const CFStringRef kSecKeyEncryptionParameterRecryptParameters
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @constant kSecKeyEncryptionParameterRecryptCertificate Usable only inside kSecKeyEncryptionParameterRecryptParameters.
+ Specifies certificate whose public key is used to re-crypt previously decrypted data. This parameter should contain
+ CFDataRef with X509 DER-encoded data of the certificate chain {leaf, intermediate, root}, leaf's public key is
+ to be used for re-encryption.
+ */
+extern const CFStringRef kSecKeyEncryptionParameterRecryptCertificate
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @function SecKeyCreateEncryptedDataWithParameters
+ @abstract Encrypt a block of plaintext.
+ @param key Public key with which to encrypt the data.
+ @param algorithm One of SecKeyAlgorithm constants suitable to perform encryption with this key.
+ @param plaintext The data to encrypt. The length and format of the data must conform to chosen algorithm,
+ typically be less or equal to the value returned by SecKeyGetBlockSize().
+ @param parameters Dictionary with additional parameters for encryption. Supported parameters are:
+  - kSecKeyKeyExchangeParameterSharedInfo: additional SharedInfo value for ECIES encryptions
+  - kSecKeyEncryptionParameterSymmetricKeySizeInBits: 128 or 256, size of ephemeral AES key used for symmetric encryption
+  - kSecKeyEncryptionParameterSymmetricAAD: optional CFDataRef with additiona authentication data for AES-GCM encryption
+ @param error On error, will be populated with an error object describing the failure.
+ See "Security Error Codes" (SecBase.h).
+ @result The ciphertext represented as a CFData, or NULL on failure.
+ @discussion Encrypts plaintext data using specified key.  The exact type of the operation including the format
+ of input and output data is specified by encryption algorithm.
+ */
+CFDataRef SecKeyCreateEncryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext,
+                                                  CFDictionaryRef parameters, CFErrorRef *error)
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
+/*!
+ @function SecKeyCreateDecryptedDataWithParameters
+ @abstract Decrypt a block of ciphertext.
+ @param key Private key with which to decrypt the data.
+ @param algorithm One of SecKeyAlgorithm constants suitable to perform decryption with this key.
+ @param ciphertext The data to decrypt. The length and format of the data must conform to chosen algorithm,
+ typically be less or equal to the value returned by SecKeyGetBlockSize().
+ @param parameters Dictionary with additional parameters for decryption.Supported parameters are:
+  - kSecKeyKeyExchangeParameterSharedInfo: additional SharedInfo value for ECIES encryptions
+  - kSecKeyEncryptionParameterSymmetricKeySizeInBits: 128 or 256, size of ephemeral AES key used for symmetric encryption
+  - kSecKeyEncryptionParameterSymmetricAAD: optional CFDataRef with additiona authentication data for AES-GCM encryption
+  - kSecKeyEncryptionParameterRecryptParameters: optional CFDictionaryRef with parameters for immediate re-encryption
+    of decrypted data. If present, the dictionary *must* contain at least kSecKeyEncryptionParameterRecryptCertificate parameter.
+
+ @param error On error, will be populated with an error object describing the failure.
+ See "Security Error Codes" (SecBase.h).
+ @result The plaintext represented as a CFData, or NULL on failure.
+ @discussion Decrypts ciphertext data using specified key.  The exact type of the operation including the format
+ of input and output data is specified by decryption algorithm.
+ */
+CFDataRef SecKeyCreateDecryptedDataWithParameters(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext,
+                                                  CFDictionaryRef parameters, CFErrorRef *error)
+SPI_AVAILABLE(macos(10.14.4), ios(12.2), tvos(12.2), watchos(5.2));
+
 /*!
  @enum SecKeyAttestationKeyType
  @abstract Defines types of builtin attestation keys.
@@ -716,9 +798,9 @@ typedef CF_ENUM(uint32_t, SecKeyAttestationKeyType)
 {
     kSecKeyAttestationKeyTypeSIK = 0,
     kSecKeyAttestationKeyTypeGID = 1,
-    kSecKeyAttestationKeyTypeUIKCommitted API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 2,
-    kSecKeyAttestationKeyTypeUIKProposed API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 3,
-} API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
+    kSecKeyAttestationKeyTypeUIKCommitted SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 2,
+    kSecKeyAttestationKeyTypeUIKProposed SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 3,
+} SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
 
 /*!
  @function SecKeyCopyAttestationKey
@@ -730,7 +812,7 @@ typedef CF_ENUM(uint32_t, SecKeyAttestationKeyType)
  @result On success a SecKeyRef containing the requested key is returned, on failure it returns NULL.
 */
 SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef *error)
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
+SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
 
 /*!
  @function SecKeyCreateAttestation
@@ -745,7 +827,7 @@ API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
  @discussion Key attestation only works for CTK SEP keys, i.e. keys created with kSecAttrTokenID=kSecAttrTokenIDSecureEnclave.
 */
 CFDataRef SecKeyCreateAttestation(SecKeyRef key, SecKeyRef keyToAttest, CFErrorRef *error)
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
+SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
 
 /*!
  @function SecKeySetParameter
@@ -761,10 +843,10 @@ API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
  SecKey user (application) and backend and in this case are not interpreted by SecKey layer in any way.
  */
 Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error)
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
+SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
 
 extern const CFStringRef kSecKeyParameterSETokenAttestationNonce
-API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
+SPI_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
 
 /*!
  Available lifetime operations for SEP system keys.
@@ -772,7 +854,7 @@ API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
 typedef CF_ENUM(int, SecKeyControlLifetimeType) {
     kSecKeyControlLifetimeTypeBump = 0,
     kSecKeyControlLifetimeTypeCommit = 1,
-} API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0));
+} SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0));
 
 /*!
  @function SecKeyControlLifetime
@@ -783,7 +865,7 @@ typedef CF_ENUM(int, SecKeyControlLifetimeType) {
  @param error Error which gathers more information when something went wrong.
  */
 Boolean SecKeyControlLifetime(SecKeyRef key, SecKeyControlLifetimeType type, CFErrorRef *error)
-API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0));
+SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0));
 
 /*!
  @function SecKeyCreateDuplicate
@@ -796,7 +878,7 @@ API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0));
  If the key is immutable (i.e. does not support SecKeySetParameter), calling this method is identical to calling CFRetain().
  */
 SecKeyRef SecKeyCreateDuplicate(SecKeyRef key)
-API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
+SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0));
 
 /*!
  Algorithms for converting between bigendian and core-crypto ccunit data representation.
index d6eeb2256e3512472001a0283875d54343a863ac..6e35c084c11facffb5853d5beaba203197afc3ad 100644 (file)
@@ -61,6 +61,7 @@ extern CKKSItemState* const SecCKKSStateUnauthenticated;
 extern CKKSItemState* const SecCKKSStateInFlight;
 extern CKKSItemState* const SecCKKSStateReencrypt;
 extern CKKSItemState* const SecCKKSStateError;
+extern CKKSItemState* const SecCKKSStateZoneMismatch; // an item has appeared that's in the wrong zone
 extern CKKSItemState* const SecCKKSStateDeleted;  // meta-state: please delete this item!
 
 /* Processed States */
index c760202100fd0c390f84669edf1dd2a33c2f27ff..3d80c47d6bba92c3ce51dfcdba4cae60f63b7886 100644 (file)
@@ -50,6 +50,7 @@ CKKSItemState* const SecCKKSStateUnauthenticated = (CKKSItemState*) @"unauthenti
 CKKSItemState* const SecCKKSStateInFlight = (CKKSItemState*) @"inflight";
 CKKSItemState* const SecCKKSStateReencrypt = (CKKSItemState*) @"reencrypt";
 CKKSItemState* const SecCKKSStateError = (CKKSItemState*) @"error";
+CKKSItemState* const SecCKKSStateZoneMismatch = (CKKSItemState*) @"zone_mismatch";
 CKKSItemState* const SecCKKSStateDeleted = (CKKSItemState*) @"deleted";
 
 CKKSProcessedState* const SecCKKSProcessedStateLocal = (CKKSProcessedState*) @"local";
index 3132c6d0fc7f675ec1af0d8f38c2badaf25b0849..f3f53f19b28c84b46ab05cbc8412a585b9768eef 100644 (file)
                 continue;
             }
 
+
+            // Now, filter: if this item was added locally, would it go to this view?
+            // In this release, this is based solely on viewhint
+            NSString* viewHint = attributes[(id)kSecAttrSyncViewHint];
+            bool itemIsForView = [viewHint isEqualToString: ckks.zoneName];
+            if(!itemIsForView) {
+
+                ckkserror("ckksincoming", ckks, "ViewHint in decrypted item (%@) does not match (%@), skipping item", viewHint, ckks.zoneName);
+                iqe.state = SecCKKSStateZoneMismatch;
+                [iqe saveToDatabase:&error];
+                if(error) {
+                    ckkserror("ckksincoming", ckks, "Couldn't save zone mismatch IQE to database: %@", error);
+                    self.error = error;
+                }
+                continue;
+            }
+
             if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) {
                 BOOL requireManifestValidation = [CKKSManifest shouldEnforceManifests];
                 BOOL manifestValidatesItem = [manifest validateItem:iqe.item withError:&error];
index 965c28f212bccd6b7e5a9c1468872a4b3b1685f3..07e5b98780a9509758ce5543bc461d4dc510d0cb 100644 (file)
 
                                                                        // Ugly, but: the Manatee and Engram views need to send a fake 'PCS' view change.
                                                                        // TODO: make this data-driven somehow
-                                                                       if([strongSelf.zoneName isEqualToString:@"Manatee"] || [strongSelf.zoneName isEqualToString:@"Engram"]) {
+                                                                       if([strongSelf.zoneName isEqualToString:@"Manatee"] ||
+                                                                          [strongSelf.zoneName isEqualToString:@"Engram"] ||
+                                                                          [strongSelf.zoneName isEqualToString:@"ApplePay"] ||
+                                                                          [strongSelf.zoneName isEqualToString:@"LimitedPeersAllowed"]) {
                                                                            [strongSelf.notifierClass post:@"com.apple.security.view-change.PCS"];
                                                                        }
                                                                    }];
index ace523439096cedb859427357ef34281da22a779..664d69deba227b76a360d100734dc80e97eaa039 100644 (file)
 @property FakeCKZone*          homeZone;
 @property (readonly) ZoneKeys* homeZoneKeys;
 
+@property CKRecordZoneID*      limitedZoneID;
+@property CKKSKeychainView*    limitedView;
+@property FakeCKZone*          limitedZone;
+@property (readonly) ZoneKeys* limitedZoneKeys;
+
 @end
 
 @implementation CloudKitKeychainSyncingSOSIntegrationTests
     [self.ckksZones addObject:self.applepayZoneID];
 
     self.homeZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Home" ownerName:CKCurrentUserDefaultName];
-    self.homeZone = [[FakeCKZone alloc] initZone: self.healthZoneID];
+    self.homeZone = [[FakeCKZone alloc] initZone: self.homeZoneID];
     self.zones[self.homeZoneID] = self.homeZone;
     self.homeView = [[CKKSViewManager manager] findView:@"Home"];
     XCTAssertNotNil(self.homeView, "CKKSViewManager created the Home view");
     [self.ckksZones addObject:self.homeZoneID];
+
+    self.limitedZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"LimitedPeersAllowed" ownerName:CKCurrentUserDefaultName];
+    self.limitedZone = [[FakeCKZone alloc] initZone: self.limitedZoneID];
+    self.zones[self.limitedZoneID] = self.limitedZone;
+    self.limitedView = [[CKKSViewManager manager] findView:@"LimitedPeersAllowed"];
+    XCTAssertNotNil(self.limitedView, "CKKSViewManager created the LimitedPeersAllowed view");
+    [self.ckksZones addObject:self.limitedZoneID];
 }
 
 + (void)tearDown {
     [self startCKKSSubsystem];
 
     XCTestExpectation* applepayChanged = [self expectChangeForView:self.applepayZoneID.zoneName];
-    // ApplePay is NOT is PCS view, so it should not send the fake 'PCS' view notification
     XCTestExpectation* pcsChanged = [self expectChangeForView:@"PCS"];
-    pcsChanged.inverted = YES;
+
 
     // We expect a single record to be uploaded to the ApplePay view.
     [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.applepayZoneID];
     [self waitForExpectations:@[pcsChanged] timeout:0.2];
 }
 
+-(void)testAddLimitedPeersAllowedItems {
+    [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test.
+
+    [self startCKKSSubsystem];
+
+    XCTestExpectation* limitedChanged = [self expectChangeForView:self.limitedZoneID.zoneName];
+    // LimitedPeersAllowed is a PCS view, so it should send the fake 'PCS' view notification
+    XCTestExpectation* pcsChanged = [self expectChangeForView:@"PCS"];
+
+    // We expect a single record to be uploaded to the LimitedPeersOkay view.
+    [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.limitedZoneID];
+    [self addGenericPassword: @"data" account: @"account-delete-me-limited-peers" viewHint:(NSString*) kSecAttrViewHintLimitedPeersAllowed];
+
+    OCMVerifyAllWithDelay(self.mockDatabase, 20);
+    [self waitForExpectations:@[limitedChanged] timeout:1];
+    [self waitForExpectations:@[pcsChanged] timeout:0.2];
+
+    [self waitForKeyHierarchyReadinesses];
+
+    // Let's also test that an item added by a future peer (lacking the right viewhint) doesn't sync
+    NSMutableDictionary* item = [[self fakeRecordDictionary:@"asdf" zoneID:self.limitedZoneID] mutableCopy];
+    item[(id)kSecAttrSyncViewHint] = @"new-view";
+
+    CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"37E6CA21-A586-44E1-9A1C-3EE464C78EB5" zoneID:self.limitedZoneID];
+    CKRecord* ckr = [self newRecord:ckrid withNewItemData:item];
+    [self.limitedZone addToZone:ckr];
+    ckr = [self createFakeRecord:self.limitedZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2AAA" withAccount:@"asdf-exist"];
+    [self.limitedZone addToZone:ckr];
+
+    [self.limitedView notifyZoneChange:nil];
+    [self.limitedView waitForFetchAndIncomingQueueProcessing];
+
+    [self findGenericPassword:@"asdf-exist" expecting:errSecSuccess];
+    [self findGenericPassword:@"asdf" expecting:errSecItemNotFound];
+
+    NSError *error = NULL;
+    XCTAssertEqual([CKKSIncomingQueueEntry countByState:SecCKKSStateZoneMismatch zone:self.limitedZoneID error:&error],
+                   1,
+                   "Expected a ZoneMismatch entry in incoming queue: %@", error);
+    XCTAssertNil(error, "Should be no error fetching incoming queue entries");
+}
+
 -(void)testAddOtherViewHintItem {
     [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test.
 
     [self putFakeDeviceStatusInCloudKit: self.healthZoneID];
     [self putFakeDeviceStatusInCloudKit: self.applepayZoneID];
     [self putFakeDeviceStatusInCloudKit: self.homeZoneID];
+    [self putFakeDeviceStatusInCloudKit: self.limitedZoneID];
 }
 
 -(void)putFakeKeyHierachiesInCloudKit{
     [self putFakeKeyHierarchyInCloudKit: self.healthZoneID];
     [self putFakeKeyHierarchyInCloudKit: self.applepayZoneID];
     [self putFakeKeyHierarchyInCloudKit: self.homeZoneID];
+    [self putFakeKeyHierarchyInCloudKit: self.limitedZoneID];
 }
 -(void)saveTLKsToKeychain{
     [self saveTLKMaterialToKeychain:self.engramZoneID];
     [self saveTLKMaterialToKeychain:self.healthZoneID];
     [self saveTLKMaterialToKeychain:self.applepayZoneID];
     [self saveTLKMaterialToKeychain:self.homeZoneID];
+    [self saveTLKMaterialToKeychain:self.limitedZoneID];
 }
 -(void)deleteTLKMaterialsFromKeychain{
     [self deleteTLKMaterialFromKeychain: self.engramZoneID];
     [self deleteTLKMaterialFromKeychain: self.healthZoneID];
     [self deleteTLKMaterialFromKeychain: self.applepayZoneID];
     [self deleteTLKMaterialFromKeychain: self.homeZoneID];
+    [self deleteTLKMaterialFromKeychain:self.limitedZoneID];
 }
 
 -(void)waitForKeyHierarchyReadinesses {
     [self.healthView waitForKeyHierarchyReadiness];
     [self.applepayView waitForKeyHierarchyReadiness];
     [self.homeView waitForKeyHierarchyReadiness];
+    [self.limitedView waitForKeyHierarchyReadiness];
 }
 
 -(void)testAcceptExistingAndUsePiggyKeyHierarchy {
index 9fc7a7c90961a9774b5b01232fb398add843d1e3..951dd0f6d767fb637a66a5265d9f246ef98c2fa3 100644 (file)
@@ -62,6 +62,7 @@
               (id)kSecClass : (id)kSecClassGenericPassword,
               (id)kSecReturnPersistentRef: @YES,
               (id)kSecReturnAttributes: @YES,
+              (id)kSecAttrSyncViewHint: @"keychain",
               (id)kSecAttrAccessGroup : @"com.apple.security.ckks",
               (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock,
               (id)kSecAttrAccount : account,
index d89f20a18e390d1db642e1d652c2a9a8eceb0c85..c7fedf83861da6b135a6614b5f7095c50998594f 100644 (file)
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
                                                   PCSPublicKey:publicKey
                                              PCSPublicIdentity:publicIdentity]];
 
-    result = [self pcsAddItem:@"tOTHER-ITEM"
+    result = [self pcsAddItem:@"OTHER-ITEM"
                          data:[@"asdfasdf" dataUsingEncoding:NSUTF8StringEncoding]
             serviceIdentifier:(NSNumber*)servIdentifier
                     publicKey:(NSData*)publicKey
 
     // Check that the record is where we expect it
     [self waitForCKModifications];
-    CKRecordID* pcsOtherItemRecordID = [[CKRecordID alloc] initWithRecordName: @"878BEAA6-1EE9-1079-1025-E6832AC8F2F3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsOtherItemRecordID = [[CKRecordID alloc] initWithRecordName: @"11D16E4E-F9F7-6940-938C-78BAC4D56953" zoneID:self.keychainZoneID];
     CKRecord* recordOther = self.keychainZone.currentDatabase[pcsOtherItemRecordID];
     XCTAssertNotNil(recordOther, "Found other record in CloudKit at expected UUID");
 
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
 
     // Check that the records are where we expect them in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
-    CKRecordID* pcsItemRecordID2 = [[CKRecordID alloc] initWithRecordName: @"3AB8E78D-75AF-CFEF-F833-FA3E3E90978A" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID2 = [[CKRecordID alloc] initWithRecordName: @"10E76B80-CE1C-A52A-B0CB-462A2EBA05AF" zoneID:self.keychainZoneID];
     CKRecord* record2 = self.keychainZone.currentDatabase[pcsItemRecordID2];
     XCTAssertNotNil(record2, "Found 2nd record in CloudKit at expected UUID");
 
 
     // Another machine comes along and updates the pointer!
     CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice"
-                                                                    currentItemUUID:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3"
+                                                                    currentItemUUID:@"50184A35-4480-E8BA-769B-567CF72F1EC0"
                                                                               state:SecCKKSProcessedStateRemote
                                                                              zoneID:self.keychainZoneID
                                                                     encodedCKRecord:nil];
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
 
     // Another machine comes along and updates the pointer!
     CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice"
-                                                                    currentItemUUID:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3"
+                                                                    currentItemUUID:@"50184A35-4480-E8BA-769B-567CF72F1EC0"
                                                                               state:SecCKKSProcessedStateRemote
                                                                              zoneID:self.keychainZoneID
                                                                     encodedCKRecord:nil];
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    NSString* recordUUID = @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3";
+    NSString* recordUUID = @"50184A35-4480-E8BA-769B-567CF72F1EC0";
     CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName:recordUUID zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
     // Check that the number is on the CKKSMirrorEntry
     [self.keychainView dispatchSync: ^bool {
         NSError* error = nil;
-        CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID error:&error];
+        CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID error:&error];
 
         XCTAssertNil(error, "no error fetching ckme");
         XCTAssertNotNil(ckme, "Received a ckme");
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
 
     // Check that the record is where we expect it in CloudKit
     [self waitForCKModifications];
-    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID];
     XCTAssertNotNil(record, "Found record in CloudKit at expected UUID");
 
     XCTAssertNil(error, "Error should be nil parsing base64 item");
 
     item[@"v_Data"] = [@"conflictingdata" dataUsingEncoding:NSUTF8StringEncoding];
-    CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID];
+    item[@"vwht"] = self.keychainZoneID.zoneName;
+    CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
     CKRecord* mismatchedRecord = [self newRecord:ckrid withNewItemData:item];
     [self.keychainZone addToZone: mismatchedRecord];
 
index c5a7706ed3540e72b9bc93386fab792097d0a9e2..57df961b975bbb9a0ba3ac001aaa186ca6a07462 100644 (file)
@@ -532,8 +532,11 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i,
     SecAsn1Item *contentType, *digest;
     OSStatus status;
 
-    cinfo = &(sigd->contentInfo);
+    if (sigd == NULL || sigd->signerInfos == NULL || i >= SecCmsSignedDataSignerInfoCount(sigd)) {
+        return errSecParam;
+    }
 
+    cinfo = &(sigd->contentInfo);
     signerinfo = sigd->signerInfos[i];
 
     /* Signature or digest level verificationStatus errors should supercede
@@ -541,15 +544,21 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i,
 
     /* Find digest and contentType for signerinfo */
     algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo);
+    if (algiddata == NULL) {
+        return errSecInvalidDigestAlgorithm;
+    }
 
     if (!sigd->digests) {
-       SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd);
-       SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs);
-       SecCmsSignedDataSetDigestContext(sigd, digcx);
-       SecCmsDigestContextDestroy(digcx);
+        SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd);
+        SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs);
+        SecCmsSignedDataSetDigestContext(sigd, digcx);
+        SecCmsDigestContextDestroy(digcx);
     }
 
     digest = SecCmsSignedDataGetDigestByAlgTag(sigd, algiddata->offset);
+    if (digest == NULL) {
+        return errSecDataNotAvailable;
+    }
 
     contentType = SecCmsContentInfoGetContentTypeOID(cinfo);
 
index 03a4ac46592557b2bfe7cd7d89a14203a479192f..9ce04a93c3d40f5847b16e21da91d476204ea6f1 100644 (file)
Binary files a/resources/English.lproj/OID.strings and b/resources/English.lproj/OID.strings differ
index fb6330cfc9dad036f6b46942d162855293f409b1..70b8bdaf89dc7eaedde4f23616e9ad9bf420736d 100644 (file)
Binary files a/resources/English.lproj/Trust.strings and b/resources/English.lproj/Trust.strings differ
index 11b2b4b68eab439fb1854fee03cca17f65752b85..57b635c03c6191fac87f09af8d9d6be7d8863b6c 100644 (file)
@@ -150,8 +150,8 @@ csops_task(SecTaskRef task, int ops, void *blob, size_t size)
        return rc;
 }
 
-CFStringRef
-SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error)
+static CFStringRef
+SecTaskCopyIdentifier(SecTaskRef task, int op, CFErrorRef *error)
 {
         CFStringRef signingId = NULL;
         char *data = NULL;
@@ -159,7 +159,7 @@ SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error)
         uint32_t bufferlen;
         int ret;
 
-        ret = csops_task(task, CS_OPS_IDENTITY, &header, sizeof(header));
+        ret = csops_task(task, op, &header, sizeof(header));
         if (ret != -1 || errno != ERANGE)
                 return NULL;
 
@@ -174,7 +174,7 @@ SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error)
                 ret = ENOMEM;
                 goto out;
         }
-        ret = csops_task(task, CS_OPS_IDENTITY, data, bufferlen);
+        ret = csops_task(task, op, data, bufferlen);
         if (ret) {
                 ret = errno;
                 goto out;
@@ -192,6 +192,18 @@ SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error)
         return signingId;
 }
 
+CFStringRef
+SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error)
+{
+    return SecTaskCopyIdentifier(task, CS_OPS_IDENTITY, error);
+}
+
+CFStringRef
+SecTaskCopyTeamIdentifier(SecTaskRef task, CFErrorRef *error)
+{
+    return SecTaskCopyIdentifier(task, CS_OPS_TEAMID, error);
+}
+
 uint32_t
 SecTaskGetCodeSignStatus(SecTaskRef task)
 {
index b72266ecb8f088a70b9191ec476267308958a939..e29aa8832d36bd4d8372131edb2a628ff5a4034d 100644 (file)
@@ -39,7 +39,7 @@ __BEGIN_DECLS
     task satisfies the requirement.
 */
 
-OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement);
+OSStatus SecTaskValidateForRequirement(SecTaskRef _Nonnull task, CFStringRef _Nonnull requirement);
 
 /*!
   @function SecTaskGetCodeSignStatus
@@ -48,7 +48,7 @@ OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement)
 */
 
 uint32_t
-SecTaskGetCodeSignStatus(SecTaskRef task);
+SecTaskGetCodeSignStatus(SecTaskRef _Nonnull task);
 #endif /* SEC_OS_OSX */
 
 /*!
@@ -57,9 +57,18 @@ SecTaskGetCodeSignStatus(SecTaskRef task);
  false the tasks entitlements must not be used for anything security sensetive.
  @param task A previously created SecTask object
  */
-Boolean SecTaskEntitlementsValidated(SecTaskRef task);
-
+Boolean SecTaskEntitlementsValidated(SecTaskRef _Nonnull task);
 
+/*!
+ @function SecTaskCopyTeamIdentifier
+ @abstract Return the value of the team identifier.
+ @param task A previously created SecTask object
+ @param error On a NULL return, this will contain a CFError describing
+ the problem.  This argument may be NULL if the caller is not interested in
+ detailed errors. The caller must CFRelease the returned value
+ */
+__nullable
+CFStringRef SecTaskCopyTeamIdentifier(SecTaskRef _Nonnull task, CFErrorRef _Nullable * _Nullable error);
 
 __END_DECLS
 
index 52bf234862afc013e429bb5a3f35680b7233b292..2286c2d43b4e06c79e806d7a030e58fdbae0a3ee 100644 (file)
@@ -123,7 +123,7 @@ static service_user_record_t * get_user_record(uid_t uid)
     if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
         bufsize = 4096;
     }
-    char buf[bufsize];
+    char *buf = calloc(1, (size_t)bufsize);
     struct passwd pwbuf, *pw = NULL;
     int rc;
     if (((rc = getpwuid_r(uid, &pwbuf, buf, bufsize, &pw)) == 0) && pw != NULL) {
@@ -138,6 +138,7 @@ static service_user_record_t * get_user_record(uid_t uid)
     }
 
 done:
+    free(buf);
     return ur;
 }
 
index df1647eee0b16d55c40cc8acb6b35f1f5c3e8204..60176b1b7e2d182b36314268adab519dae24b8ef 100644 (file)
@@ -32,6 +32,7 @@
 #include <security_utilities/crc.h>
 #include <security_utilities/casts.h>
 #include <unistd.h>
+#include <vector>
 
 /*
     Logically, these should go in /var/run/mds, but we know that /var/db/mds
@@ -153,13 +154,13 @@ void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetTy
 
        // assemble the final message
        ssize_t messageSize = kHeaderLength + messageLength;
-       u_int8_t finalMessage[messageSize];
-       SegmentOffsetType *fm  = (SegmentOffsetType*) finalMessage;
+       std::vector<u_int8_t> finalMessage(messageSize);
+       SegmentOffsetType *fm  = (SegmentOffsetType*) finalMessage.data();
        fm[0] = OSSwapHostToBigInt32(domain);
        fm[1] = OSSwapHostToBigInt32(event);
        memcpy(&fm[2], message, messageLength);
        
-       SegmentOffsetType crc = CalculateCRC(finalMessage, messageSize);
+       SegmentOffsetType crc = CalculateCRC(finalMessage.data(), messageSize);
        
        // write the length
        WriteOffset(int_cast<size_t, SegmentOffsetType>(messageSize));
@@ -168,7 +169,7 @@ void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetTy
        WriteOffset(crc);
        
        // write the data
-       WriteData (finalMessage, int_cast<size_t, SegmentOffsetType>(messageSize));
+       WriteData (finalMessage.data(), int_cast<size_t, SegmentOffsetType>(messageSize));
        
        // write the data count
        SetProducerOffset(int_cast<size_t, SegmentOffsetType>(mDataPtr - mDataArea));
index 88107375579e8cf16466f5b9c405337f6b48cbc9..e5004bd6df2ab9d7955fce31d2b285fa86bf050e 100644 (file)
@@ -321,6 +321,10 @@ static void xpcArrayToAuthItemSet(AuthItemSet *setToBuild, xpc_object_t input) {
         bool sensitive = xpc_dictionary_get_value(item, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
         if (sensitive) {
             size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(item, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
+            if (sensitiveLength > length) {
+                secnotice("SecurityAgentXPCQuery", "Sensitive data len %zu is not valid", sensitiveLength);
+                return true;
+            }
             dataCopy = malloc(sensitiveLength);
             memcpy(dataCopy, data, sensitiveLength);
             memset_s((void *)data, length, 0, sensitiveLength); // clear the sensitive data, memset_s is never optimized away
index 352e07d8b1e083cf0901b7cf0bd1feee63a874b9..811ccb1f194c392d3990c68fa0e0e0ce047f75af 100644 (file)
@@ -57,7 +57,7 @@ ServerChild::ServerChild()
 //
 ServerChild::~ServerChild()
 {
-       mServicePort.destroy();
+       mServicePort.deallocate();
        
        if (state() == alive) {
                this->kill(SIGTERM);            // shoot it once
@@ -119,7 +119,8 @@ void ServerChild::checkIn(Port servicePort, pid_t pid)
                {
                        StLock<Mutex> _(mCheckinLock);
                        child->mServicePort = servicePort;
-                       servicePort.modRefs(MACH_PORT_RIGHT_SEND, +1);  // retain send right
+            // The macro END_IPCS deallocates this
+            servicePort.modRefs(MACH_PORT_RIGHT_SEND, +1);    // retain send right
                        secinfo("serverchild", "%p (pid %d) checking in; resuming parent thread",
                                child, pid);
                }
index 0b80042f02bf0ab0222d0a46ace5af702d5d1b04..8c9ac64f9ca973e58a2551fad83cd46c9e9a9208 100644 (file)
@@ -45,15 +45,19 @@ ClientIdentification::ClientIdentification()
 // Initialize the ClientIdentification.
 // This creates a process-level code object for the client.
 //
-void ClientIdentification::setup(pid_t pid)
+void ClientIdentification::setup(Security::CommonCriteria::AuditToken const &audit)
 {
-       StLock<Mutex> _(mLock);
-       StLock<Mutex> __(mValidityCheckLock);
-    OSStatus rc = SecCodeCreateWithPID(pid, kSecCSDefaultFlags, &mClientProcess.aref());
-       if (rc)
-               secinfo("clientid", "could not get code for process %d: OSStatus=%d",
-                       pid, int32_t(rc));
-       mGuests.erase(mGuests.begin(), mGuests.end());
+    StLock<Mutex> _(mLock);
+    StLock<Mutex> __(mValidityCheckLock);
+    
+    audit_token_t const token = audit.auditToken();
+    OSStatus rc = SecCodeCreateWithAuditToken(&token, kSecCSDefaultFlags, &mClientProcess.aref());
+    
+    if (rc) {
+        secerror("could not get code for process %d: OSStatus=%d",
+                audit.pid(), int32_t(rc));
+    }
+    mGuests.erase(mGuests.begin(), mGuests.end());
 }
 
 
index 70c9ea22b901f43bfe8a314ece4c7e7c2fbf0aae..a64fa3eb46f50479c95b3c92299a11e4e2a67425 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "codesigdb.h"
 #include <Security/SecCode.h>
+#include <security_utilities/ccaudit.h>
 #include <security_utilities/cfutilities.h>
 #include <string>
 
@@ -60,7 +61,7 @@ protected:
        SecCodeRef processCode() const;
        SecCodeRef currentGuest() const;
 
-       void setup(pid_t pid);
+       void setup(Security::CommonCriteria::AuditToken const &audit);
 
 public:
        IFDUMP(void dump());
index fb0540310c6007be32167c3074777467675245e5..5ca68c608bc9ffe40758ce519dddb3a0f4baaf38 100644 (file)
@@ -64,13 +64,12 @@ void CodeSigningHost::reset()
        case noHosting:
                break;  // nothing to do
        case dynamicHosting:
-               mHostingPort.destroy();
-               mHostingPort = MACH_PORT_NULL;
+               mHostingPort.deallocate();
         secnotice("SecServer", "%d host unregister", mHostingPort.port());
                break;
        case proxyHosting:
                Server::active().remove(*this); // unhook service handler
-               mHostingPort.destroy(); // destroy receive right
+               mHostingPort.modRefs(MACH_PORT_RIGHT_RECEIVE, -1);
                mHostingState = noHosting;
                mHostingPort = MACH_PORT_NULL;
                mGuests.erase(mGuests.begin(), mGuests.end());
index 99d014ee98738fb75ee4e3f49adbf8dbb7312518..fcf017da108ab3065afff3a55ebf35fe731fcaae 100644 (file)
@@ -693,7 +693,12 @@ void KeychainDatabase::changePassphrase(const AccessCredentials *cred)
 {
        // get and hold the common lock (don't let other threads break in here)
        StLock<Mutex> _(common());
-       
+
+    if (!checkCredentials(cred)) {
+        secinfo("KCdb", "Cannot change passphrase for (%s): existing passphrase does not match", common().dbName());
+        MacOSError::throwMe(errSecAuthFailed);
+    }
+
        // establish OLD secret - i.e. unlock the database
        //@@@ do we want to leave the final lock state alone?
     if (common().isLoginKeychain()) mSaveSecret = true;
index 1206b157ecd0a1be07d82641ce5784eeaf2f4d43..b31937988f282dc11257cdfc598ae1e282acd221 100644 (file)
 // Construct a Process object.
 //
 Process::Process(TaskPort taskPort,    const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit)
- :  mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid())
+ :  mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()), mAudit(audit)
 {
        StLock<Mutex> _(*this);
        
        // set parent session
        parent(Session::find(audit.sessionId(), true));
-
-    // let's take a look at our wannabe client...
+       
+       // let's take a look at our wannabe client...
+       
+       // Not enough to make sure we will get the right process, as
+       // pids get recycled. But we will later create the actual SecCode using
+       // the audit token, which is unique to the one instance of the process,
+       // so this just catches a pid mismatch early.
        if (mTaskPort.pid() != mPid) {
                secnotice("SecServer", "Task/pid setup mismatch pid=%d task=%d(%d)",
-                       mPid, mTaskPort.port(), mTaskPort.pid());
+                                 mPid, mTaskPort.port(), mTaskPort.pid());
                CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED);     // you lied!
        }
-
+       
        setup(info);
-       ClientIdentification::setup(this->pid());
-
+       ClientIdentification::setup(this->audit_token());
+       
+       if(!processCode()) {
+               // This can happen if the process died in the meantime.
+               secnotice("SecServer", "no process created in setup, old pid=%d old task=%d(%d)",
+                                 mPid, mTaskPort.port(), mTaskPort.pid());
+               CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED);
+       }
+       
     // NB: ServerChild::find() should only be used to determine
     // *existence*.  Don't use the returned Child object for anything else, 
     // as it is not protected against its underlying process's destruction.  
@@ -86,7 +98,7 @@ void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const Common
        setup(info);
        CFCopyRef<SecCodeRef> oldCode = processCode();
 
-       ClientIdentification::setup(this->pid());       // re-constructs processCode()
+       ClientIdentification::setup(this->audit_token());       // re-constructs processCode()
        if (CFEqual(oldCode, processCode())) {
         secnotice("SecServer", "%p Client reset amnesia", this);
        } else {
@@ -127,8 +139,9 @@ Process::~Process()
     secinfo("SecServer", "%p client release: %d", this, this->pid());
 
     // release our name for the process's task port
-       if (mTaskPort)
-        mTaskPort.destroy();
+    if (mTaskPort) {
+        mTaskPort.deallocate();
+    }
 }
 
 void Process::kill()
index ce24dc9f6ffbef4943b0cd8c51276374a2d1e061..00be3cbde8ce3162b800125bf59b5ff159e9a8c8 100644 (file)
@@ -79,6 +79,7 @@ public:
     uid_t uid() const                  { return mUid; }
     gid_t gid() const                  { return mGid; }
     pid_t pid() const                  { return mPid; }
+    Security::CommonCriteria::AuditToken const &audit_token() const { return mAudit; }
     TaskPort taskPort() const  { return mTaskPort; }
        bool byteFlipped() const        { return mByteFlipped; }
        
@@ -110,6 +111,7 @@ private:
     pid_t mPid;                                                        // process id
     uid_t mUid;                                                        // UNIX uid credential
     gid_t mGid;                                                        // primary UNIX gid credential
+    Security::CommonCriteria::AuditToken const mAudit; // audit token
 
        // canonical local (transient) key store
        RefPointer<LocalDatabase> mLocalStore;
index 7a47c485af654b8102eff2a4abc3e98ce9c6e632..25e5af1eddce7be0fe8d645802e02dd9150ff815 100644 (file)
@@ -320,6 +320,9 @@ const CFTypeRef kAKSKeyOpUnwrap = (CFTypeRef)CFSTR("kAKSKeyOpUnwrap");
 const CFTypeRef kAKSKeyOpComputeKey = (CFTypeRef)CFSTR("kAKSKeyOpComputeKey");
 const CFTypeRef kAKSKeyOpAttest = (CFTypeRef)CFSTR("kAKSKeyOpAttest");
 const CFTypeRef kAKSKeyOpTranscrypt = (CFTypeRef)CFSTR("kAKSKeyOpTranscrypt");
+const CFTypeRef kAKSKeyOpECIESEncrypt = (CFTypeRef)CFSTR("kAKSKeyOpECIESEncrypt");
+const CFTypeRef kAKSKeyOpECIESDecrypt = (CFTypeRef)CFSTR("kAKSKeyOpECIESDecrypt");
+const CFTypeRef kAKSKeyOpECIESTranscode = (CFTypeRef)CFSTR("kAKSKeyOpECIESTranscode");
 
 
 TKTokenRef TKTokenCreate(CFDictionaryRef attributes, CFErrorRef *error)
@@ -332,11 +335,6 @@ CFTypeRef TKTokenCopyObjectData(TKTokenRef token, CFDataRef objectID, CFErrorRef
     return NULL;
 }
 
-CFDataRef TKTokenCopyObjectCreationAccessControl(TKTokenRef token, CFDictionaryRef objectAttributes, CFErrorRef *error)
-{
-    return NULL;
-}
-
 CFDataRef TKTokenCreateOrUpdateObject(TKTokenRef token, CFDataRef objectID, CFMutableDictionaryRef attributes, CFErrorRef *error)
 {
     return NULL;